1 PARTE I – Cuidados antes de começar a rodar os códigos no R

##Abrindo o Projeto Monitora.Rproj

Para que o arquivo tutorial_fluxo_analises.Rmd funcione de maneira adequada em sua mĂĄquina, vocĂȘ deve descompactar o arquivo piper3D_monitora_florestal.zip. Uma nova pasta com o mesmo nome serĂĄ criada no diretĂłrio escolhido para executar a descompactação. Nela, vocĂȘ deverĂĄ clicar duas vezes sobre o Ă­cone Monitora.Rproj para começar a executar os arquivos contidos no projeto. Ao realizar esse procedimento, vocĂȘ garantirĂĄ que seu diretĂłrio de trabalho esteja configurado como o diretĂłrio da pasta piper3d_monitora_florestal assegurando o funcionamento correto dos cĂłdigos contidos no projeto.

1.1 Dicas sobre RMarkdown

Os cĂłdigos deste arquivo estĂŁo disponĂ­veis em chunks, que podem ser rodados individualmente.

Caso nĂŁo queira rodar parte dos cĂłdigos, vocĂȘ pode bloquear os chunks atravĂ©s do argumento eval=FALSE na linha de comando dos chunks, conforme exemplo:

Caso nĂŁo queira nem incluir os cĂłdigos no relatĂłrio resultante, nem rodar os cĂłdigos, vocĂȘ pode usar os argumentos echo=FALSE e eval=FALSE na linha de comando dos chunks, conforme exemplo:

Caso não queira que os resultados de algum código apareçam no relatório final, usar:

Caso queira omitir do relatĂłrio mensagens de avisos ou advertĂȘncias, usar:

1.2 ** Instalando e carregando o pacote distenceMonitoraflorestal**

# devtools::install_github("vntborgesjr/distanceMonitoraflorestal")
# 
library(distanceMonitoraflorestal)

1.3 Carregando os pacotes

1.4 Rstudio/Pacotes/versÔes/sistemas operacionais

A tabela aseguir Ă© uma referĂȘncia para as versĂ”es dos pacotes utilizados no nesse projeto. Para garantir a reprodução dos cĂłdigos, Ă© importante que o R e os pacotes usados no projeto apresentem as configuraçÔes mĂ­nimas contidas na tabela 1.

# # gerar informaçÔes sobre os pacotes carregados
# info <- sessionInfo()
# 
# # gerar tabela com os pacotes e versÔes
# tribble(
#   ~Pacotes,                         ~VersĂŁo,
#   version$language,                 version$version.string,
#   info$otherPkgs$dplyr$Package,     info$otherPkgs$dplyr$Version,
#   info$otherPkgs$Distance$Package,  info$otherPkgs$Distance$Version,
#   info$otherPkgs$DT$Package,        info$otherPkgs$DT$Version,
#   info$otherPkgs$forcats$Package,        info$otherPkgs$forcats$Version,
#   info$otherPkgs$flextable$Package, info$otherPkgs$flextable$Version,
#   info$otherPkgs$ggplot2$Package,     info$otherPkgs$ggplot2$Version,
#   info$otherPkgs$ggpubr$Package,     info$otherPkgs$ggpubr$Version,
#   info$otherPkgs$here$Package,     info$otherPkgs$here$Version,
#   info$otherPkgs$lubridate$Package, info$otherPkgs$lubridate$Version,
#   info$otherPkgs$mrds$Package,     info$otherPkgs$mrds$Version,
#   info$otherPkgs$plotly$Package,    info$otherPkgs$plotly$Version,
#   info$otherPkgs$purrr$Package,     info$otherPkgs$purrr$Version,
#   info$otherPkgs$readr$Package,     info$otherPkgs$readr$Version,
#   info$otherPkgs$readxl$Package,     info$otherPkgs$readxl$Version,
#   info$otherPkgs$stringi$Package,     info$otherPkgs$stringi$Version,
#   info$otherPkgs$stringr$Package,     info$otherPkgs$stringr$Version,
#   info$otherPkgs$tibble$Package,    info$otherPkgs$tibble$Version,
#   info$otherPkgs$tidyr$Package,     info$otherPkgs$tidyr$Version,
#   info$otherPkgs$tidyselect$Package,info$otherPkgs$tidyselect$Version
# ) |> 
#   flextable::qflextable() |> 
#   flextable::set_caption(
#     "Tabela 1 - configuração de pacotes necessårios e respectivas versÔes mínimas que devem ser utilizadas para reproduzir os códigos"
#   )

1.5 Cuidados com a planilha .xlsx que serĂĄ importada (para que mantenha o padrĂŁo da planilha de referĂȘncia do ICMBio)

A primeira função utlizada, carregar_dados_brutos_xlsx(), irĂĄ carregar a planilha em formato excel, Planilha Oficial consolidada de Masto-aves 2014-21 Validada CEMAVE CPB CENAP.xlsx, e gera automaticamente o arquivo dados_brutos.rds na pasta data-raw. A função seguinte a ser utilizada, carregar_dados_completos() que irĂĄ carregar o arquivo dados_brutos.rds. Essa função foi escrita para carrega os dados e operar uma sĂ©rie de transformaçÔes para devolvĂȘ-lo no formato padronizado do programa DISTANCE para Windows. Portanto, para garantir a reprodutibilidade dos cĂłdigos produzidos em versĂ”es atualizadas da base de dados do Monitora, Ă© importante tomar alguns cuidados.

O primeiro e mais importante cuidado Ă© manter a consistĂȘncia dos nomes das colunas em versĂ”es atualizadas da base de dados do Monitora. AlĂ©m de carregar os dados, a função carregar_dados_completos() aplica uma sĂ©rie de transformaçÔes nas colunas. Seus nomes sĂŁo alterados, e a essas sĂŁo atribuĂ­dos tipos apropriados (data, caracter, fator, inteiro e numĂ©rico), linhas sĂŁo eliminadas e novas colunas sĂŁo gereadas. Para exemplificar, veja o cĂłdigo abaixo. Ele foi escrito para executar as primeiras transformaçÔes nos dados e constitui o corpo da função carregar_dados_filtrados().

# # carregar a base de dados do Monitora
# dados_brutos <- carregar_dados_brutos_xlsx()
# 
# # gerar o data.frame desejado reproduzindo as transformaçÔes realizadas pela função carregar_dados_completos()
# dados_filtrados <- dados_brutos |>  
#   # selecionar as colunas necessĂĄrias para as analises, padronizando os nomes para o formato DISTANCE
#   dplyr::select(
#     uc_code = CDUC,
#     uc_name = `Local - Nome da Unidade de Conservacao`,
#     ea_number = `Numero da Estacao Amostral`,
#     ea_name = `Nome da EA`,
#     season = `Estacao do ano`,
#     sampling_day = `data da amostragem`,
#     day_effort = `Esforco de amostragem tamanho da trilha (m)`,
#     sp = `Especies validadas para analise do ICMBio`,
#     distance = `distancia (m)     do animal em relacao a trilha`,
#     group_size = `n de animais`,
#     observadores = `nome dos observadores`
#   ) |>
#   # atribuir os tipos corretos Ă s colunas e criar novas colunas
#     dplyr::mutate(
#       uc_category = stringi::stri_extract_first_words(
#       uc_name
#     ),
#     # abrevia o nome das UCs
#     uc_name_abv = forcats::lvls_revalue(
#       uc_name,
#       new_levels = c(
#         "ETM", "EM", "EN", "ESGT", "FJ", "PCV", "PA", "PSBoc", "PSBod", "PSC",
#         "PSM", "PSC", "PSD", "PSP", "PSO", "PPN", "PCO", "PI", "PJaĂș", "PJur",
#         "PMR", "PS", "PV", "PCA", "PMT", "RG", "RJ", "RTap", "RU", "RG",
#         "RTrom", "RAT", "RBA", "RCI", "RCM", "RRC", "RROP", "RIA", "RRA", "RTA"
#       )
#     ),
#       # atribuir o tipo data Ă  coluna sampling_day
#       year = lubridate::year(
#         sampling_day
#       ),
#       # atribuir o tipo fator Ă s colunas do tipo caracter
#       across(
#         where(
#           is.character
#         ),
#         as.factor
#       ),
#       # substituir separadores de nome por ","
#       novo = stringr::str_replace_all(
#         observadores, 
#         " e ",
#         ", "
#       ),
#       # substituir separadores de nome por ","
#       novo = stringr::str_replace_all(
#         novo, 
#         " E ",
#         ", "
#       ),
#       # substituir separadores de nome por ","
#       novo = stringr::str_replace_all(
#         novo, 
#         "/",
#         ", "
#       ),
#       # substituir separadores de nome por ","
#       novo = stringr::str_replace_all(
#         novo, 
#         ";",
#         ", "
#       ),
#       # substituir separadores de nome por ","
#       novo = stringr::str_replace_all(
#         novo, 
#         " a ",
#         ", "
#       ) 
#     ) |>
#   # transformar os nomes dos observadores da coluna novo em colunas individuais
# tidyr::separate_wider_delim(
#   novo, 
#   ",",
#   names = c(
#     "obs1", "obs2", "obs3", "obs4", "obs5", "obs6"
#   ),
#   too_few = "align_start"
# ) |> 
#   # gerar uma nova coluna number_observers com o nĂșmero total de observadores em um mesmo transecto
#   dplyr::mutate(
#     # se o valor da observação é diferente de NA, substituir por 1, se for NA, substituir por 0
#     obs1 = ifelse(!is.na(obs1), 1, 0),
#     obs2 = ifelse(!is.na(obs2), 1, 0),
#     obs3 = ifelse(!is.na(obs3), 1, 0),
#     obs4 = ifelse(!is.na(obs4), 1, 0),
#     obs5 = ifelse(!is.na(obs5), 1, 0),
#     obs6 = ifelse(!is.na(obs6), 1, 0),
#     # gera nova coluna number_observers a partir da soma das colunas de observadores individuais
#     number_observers = obs1 + obs2 + obs3 + obs4 + obs5 + obs6
#   ) |> 
#   # agrupar os dados pelas colunas ea_name e sampling_day
#   group_by(
#     ea_name, 
#     sampling_day
#   ) |> 
#   # aninhar as observaçÔes agrupadas uem listas
#   nest() |> 
#   # completar com o valor correto as linhas vazias das da variĂĄvel day_effort
#   mutate(
#     day_effort2 = purrr::map(
#       data, \(.x) rep(
#         .x$day_effort[
#           !is.na(
#             .x$day_effort
#           )
#         ][1]
#       )
#     )
#   ) |> 
#   # desanihar os dados
#   unnest(
#     c(
#       data, 
#       day_effort2
#     )
#   ) |> 
#   # desagrupar os dados
#   ungroup() |> 
#   # selecionar as colunas desejadas e excluir as indesejadas
#   select(
#     tidyselect::starts_with(c("uc", "ea")),
#     season,
#     year,
#     sampling_day,
#     day_effort = day_effort2,
#     sp:number_observers,
#     -day_effort,
#     -tidyselect::starts_with("obs")
#   ) |>
#   # filtrar os dados pela UC e espécie desejadas
#     dplyr::filter(
#       uc_name == "Resex Tapajos-Arapiuns",
#       sp == "Dasyprocta croconota"
#     ) |> 
#   relocate(
#     uc_category,
#     .before = uc_name
#   ) |> 
#   relocate(
#     uc_name_abv,
#     .after = uc_name
#   )
# 
# # gerar tabela dinĂąmica dos dados completos
# dados_filtrados |> 
#   slice(
#     1:1000
#   ) |> 
#   datatable(
#     filter = list(
#       position = "top"
#     )
#   )

O trecho do código que vai da linha 96 a 106 serve selecionar apenas as colunas de interesse presente nos dados originais. Note que os nomes das planilhas originais constam nesse trecho. Caso o nome de qualque uma dessas colunas seja alterado a função deixarå de funcionar.

Outro aspecto importante Ă© a presença de observaçÔes nĂŁo preenchidas (ex. cĂ©lulas vazias) nos dados originais. A função foi desenha para resolver alguns problemas presentes nos dados originais. Por exemplo, nas o trecho do cĂłdigo das linhas 194 a 210 as observaçÔes vazias (NAs) sĂŁo substituidas pelo valor correto na coluna day_effort. Essa correção continnuarĂĄ sendo realizada em versĂ”es atualizadas dos dados do Monitora. PorĂ©m, se outras colunas alĂ©m das que estĂŁo sendo corrigidas possuirem observaçÔes vazias os dados serĂŁo carregados e transformados, porĂ©m outras funçÔes podem ter o seu funcionamento comprometido. Por exemplo, funçÔes de visualização e do pacote Distance que podem nĂŁo funcionar devido a ausĂȘncia de observação.

Dentre todas as funçÔes de carregamento de dados, apenas carregar_dados_brutos_xlsx() carrega a base de dados originais do Monitora, diretamente do diretório data-raw/monitora_masto_aves_2023_04_04.xlsx. Ao mesmo tempo que carrega e transforma os dados, essa função gera uma versão em um formato mais leve, .rds, no diretório data-raw (data-raw/monitora_masto_aves_2023_04_04.rds). A função seguinte no fluxo de trabalho carrega a base a partir dessa versão mais leve. Logo, sempre que houver atualizaçÔes no arquivo original de dados brutos é necessårio iniciar a rotina de carregamento de dados necessariamente com a função carregar_dados_brutos_xlsx().

2 PARTE II - Checagem, seleção e transformação dos dados

2.1 Base de dados para as anĂĄlises

A base de dados para as anĂĄlise tornam-se disponĂ­veis ao usuĂĄrio com o carregamento do pacote com o nome de monitora_aves_masto_florestal. Podemos inspecionar seu conteĂșdo usando a função glimpse do pacote dplyr.

# inspecionar a base de dados
dplyr::glimpse(monitora_aves_masto_florestal)
Rows: 26,420
Columns: 19
$ nome_ea             <fct> ana, ana, ana, ana, ana, ana, ana, ana,

$ n_visitas_repetidas <int> 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,

$ codigo_uc           <dbl> 259, 259, 259, 259, 259, 259, 259, 259,

$ categoria_uc        <fct> resex, resex, resex, resex, resex, rese

$ nome_uc             <fct> resex_tapajos_arapiuns, resex_tapajos_a

$ nome_uc_abv         <fct> rta, rta, rta, rta, rta, rta, rta, rta,

$ numero_ea           <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

$ data_amostragem     <dttm> 2015-02-25, 2015-02-25, 2015-02-25, 20

$ estacao             <fct> chuvosa, chuvosa, chuvosa, chuvosa, chu

$ ano                 <dbl> 2015, 2015, 2015, 2015, 2015, 2015, 201

$ esforco_dia         <dbl> 5000, 5000, 5000, 5000, 5000, 5000, 500

$ esforco_total       <dbl> 335000, 335000, 335000, 335000, 335000,

$ nome_sp             <fct> dasyprocta_croconota, mazama_sp, dasypr

$ nome_sp_abv         <fct> dasy_croc, maza_sp, dasy_croc, pene_sp,

$ validacao           <fct> especie, genero, especie, genero, espec

$ distancia           <dbl> 10, 5, 0, 3, 3, 5, 12, 18, 30, 15, 5, 1

$ tamanho_grupo       <dbl> 1, 1, 1, 2, 1, 1, 1, 1, 20, 2, 5, 1, 5,

$ numero_observadores <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 

$ tempo_censo         <drtn> -540 mins, -540 mins, -540 mins, -540 


A base de dados de aves e mamíferos de médio e grande porte gerada a partir de amostragem por distùncia contem 26420 observaçÔes (linhas) e 19 variåveis (colunas). Dentre as variåveis, hå 8 que constituem fatores, ou seja, são variåveis categóricas com diferentes níveis (ex. nome_ea, nome_uc, nome_sp), 10 constituem variåveis numéricas contínuas (ex. numero_ea, esforco_total, distancia), 1 consituem variaǘeis numéricas inteiras (ex. ) e 2 variåveis que representam datas e tempos (ex. data_amostragem, tempo_censo). Todas as anålises utilizam essa base de dados.

2.2 Filtragem dos dados

Para conduzir as anĂĄlises de estimatica de abundĂąncia e densidade das espĂ©cies, Ă© necessĂĄrio selecionar a espĂ©cie alvo e a(s) Unidade(s) de Conservação onde esta(s) ocorre(m). Para isso, o pacote oferece uma função para filtragem e seleção dos dados chamada filtrar_dados(). A função possui trĂȘs argumentos, nome_ucs, nome_sps e validacao_obs, permite selecionar uma parte dos dados de acordo com a(s) Unidade(s) de Conservação, espĂ©cie(s) e nĂ­vel de validação taxonĂŽmico desejado, respectivamente. É possĂ­vel acessar a documentação da função filtrar_dados() usando o cĂłdigo help(filtrar_dados) ou ?filtrar_dados.

Por configuração, a função filtrar_dados() retorna a base de dados monitora_aves_masto_florestal.

# retornar a base de dados completa
filtrar_dados()

Para retornar as observaçÔes de uma ou mais Unidades de Conservação, o(s) nome(s) da(s) Unidade(s) de Conservação deve(m) ser informados usando o argumento nome_ucs.

Também é possível selecionar uma ou mais Unidades de Conservação fornecendo um vetor do tipo caracter com um ou mais elementos.

nomes_ucs
 [1] resex_tapajos_arapiuns         parna_de_pacaas_novos         
 [3] parna_da_serra_da_mocidade     parna_da_serra_do_divisor     
 [5] parna_do_jau                   rebio_do_uatuma               
 [7] parna_da_amazonia              parna_do_juruena              
 [9] rebio_trombetas                parna_montanhas_do_tumucumaque
[11] flona_do_jamari                esec_maraca                   
[13] esec_serra_geral_do_tocantins  parna_chapada_dos_veadeiros   
[15] parna_da_serra_da_bocaina      parna_da_serra_do_cipo        
[17] parna_do_cabo_orange           rebio_do_jaru                 
[19] resex_cazumba_iracema          resex_alto_tarauaca           
[21] parna_do_superagui             rebio_do_tapirape             
[23] resex_ipau_anilzinho           esec_da_terra_do_meio         
[25] resex_riozinho_do_anfrisio     rebio_do_gurupi               
[27] resex_do_rio_cautario          resex_do_rio_ouro_preto       
[29] resex_barreiro_das_antas       rebio_guaribas                
[31] parna_do_iguacu                parna_da_serra_da_bodoquena   
[33] parna_do_virua                 parna_da_serra_da_cutia       
[35] parna_da_serra_dos_orgaos      resex_chico_mendes            
[37] parna_dos_campos_amazonicos    parna_da_serra_do_pardo       
[39] esec_niquia                    parna_do_monte_roraima        
40 Levels: esec_da_terra_do_meio esec_maraca ... resex_tapajos_arapiuns
# retornar as observaçÔes de mais de uma UC
filtrar_dados(nome_ucs = nomes_ucs[2:3])

Para selecionar as observaçÔes de uma ou mais espécies, o(s) nome(s) da(s) espécie(s) ser informados usando o argumento nome_sps.

# consultar o nome das UCs
nomes_sps <- monitora_aves_masto_florestal |> 
  dplyr::distinct(nome_sp)

nomes_sps
# retornar as observaçÔes de uma UC fornecendo o nome
filtrar_dados(nome_sps = "dasyprocta_croconota")

Também é possível selecionar uma ou mais espécies fornecendo um vetor do tipo caracter com um ou mais elementos.

# gerar um vetor contendo os nomes das UCs
nomes_sps <- dplyr::pull(nomes_sps)
nomes_sps
  [1] dasyprocta_croconota            mazama_sp                      
  [3] penelope_sp                     guerlinguetus_aestuans         
  [5] nasua_nasua                     pecari_tajacu                  
  [7] sapajus_apella                  tayassuidae                    
  [9] tayassu_pecari                  dasypus_sp                     
 [11] dasyprocta_leporina             callicebus_hoffmannsi          
 [13] cuniculus_paca                  felidae                        
 [15] primates                        panthera_onca                  
 [17] cracidae                        alouatta_nigerrima             
 [19] ortalis_guttata                 mazama_nemorivaga              
 [21] crypturellus_sp                 mazama_americana               
 [23] mico_humeralifer                dasypus_novemcinctus           
 [25] mico_rondoni                    ateles_chamek                  
 [27] pithecia_irrorata               pauxi_tuberosa                 
 [29] dasyprocta_fuliginosa           psophia_viridis                
 [31] urosciurus_sp                   saguinus_weddelli              
 [33] callicebus_brunneus             calicebus_caligatus            
 [35] tinamus_sp                      eira_barbara                   
 [37] odontophorus_sp                 cebus_olivaceus                
 [39] ateles_belzebuth                alouatta_macconnelli           
 [41] ortalis_motmot                  chiropotes_chiropotes          
 [43] sapajus_macrocephalus           psophia_crepitans              
 [45] callicebus_lugens               tamandua_tetradactyla          
 [47] na                              pauxi_tomentosa                
 [49] microsciurus_flaviventer        aotus_trivirgatus              
 [51] aburria_cumanensis              dasyprocta_sp                  
 [53] myrmecophaga_tridactyla         choloepus_didactylus           
 [55] galictis_vittata                aburria_cujubi                 
 [57] cebus_unicolor                  chiropotes_albinasus           
 [59] urosciurus_spadiceus            cerdocyon_thous                
 [61] bradypus_variegatus             alouatta_juara                 
 [63] penelope_jacquacu               saimiri_macrodon               
 [65] pithecia_monachus               saguinus_sp                    
 [67] lagothrix_poeppigii             crax_globulosa                 
 [69] callimico_goeldii               cacajao_calvus                 
 [71] microsciurus_sp                 cebus_albifrons                
 [73] pithecia_pithecia               myoprocta_pratti               
 [75] saimiri_cassiquiarensis         lontra_longicaudis             
 [77] cacajao_melanocephalus          urosciurus_igniventris         
 [79] odontophorus_gujanensis         pauxi_sp                       
 [81] psophia_ochroptera              tinamus_major                  
 [83] myoprocta_acouchy               chiropotes_chiropotes_sagulatus
 [85] ateles_paniscus                 crax_alector                   
 [87] nothocrax_urumutum              saguinus_midas                 
 [89] tapirus_terrestris              saimiri_sciureus               
 [91] cyclopes_didactylus             leopardus_wiedii               
 [93] priodontes_maximus              sciuridae                      
 [95] tinamidae                       puma_concolor                  
 [97] saimiri_ustus                   cabassous_unicinctus           
 [99] aotus_nigriceps                 coendou_prehensilis            
[101] didelphis_marsupialis           atelocynus_microtis            
[103] mico_sp                         pteronura_brasiliensis         
[105] hydrochoerus_hydrochaeris       callicebus_sp                  
[107] mico_melanurus                  lagothrix_cana                 
[109] callicebus_moloch               alouatta_sp                    
[111] sciurillus_pusillus             alouatta_puruensis             
[113] callicebus_cinerascens          callitrichidae                 
[115] crax_fasciolata                 bradypus_sp                    
[117] leopardus_tigrinus              chiropotes_sagulatus           
[119] penelope_marail                 puma_yagouaroundi              
[121] leopardus_pardalis              tinsmidae                      
[123] dasyprocta_prymnolopha          speothos_venaticus             
[125] nothura_sp                      penelope_obscura               
[127] tinamus_solitarius              guerlinguetus_ingrami          
[129] odontophorus_capueira           sapajus_nigritus               
[131] callithrix_aurita               alouatta_guariba               
[133] callithrix_jacchus              callithrix_penicillata         
[135] rhynchotus_rufescens            canis_familiaris               
[137] pitheciidae                     psophia_leucoptera             
[139] saimiri_boliviensis             aotus_infulatus                
[141] coendou_sp                      bradypus_tridactylus           
[143] dasyprocta_cf_fuliginosa        callicebus_bernhardi           
[145] callicebus_cupreus              saimiri_collinsi               
[147] alouatta_belzebul               psophia_interjecta             
[149] saguinus_niger                  chiropotes_utahickae           
[151] saguinus_imperator              dasypus_kappleri               
[153] guerlinguetus_ignitus           odontophorus_stellatus         
[155] coendou_bicolor                 mico_argentatus                
[157] saimiri_collinsii               gerliguetus_aestuans           
[159] callicebus_vieirai              psophia_dextralis              
[161] ateles_marginatus               mico_emiliae                   
[163] chiropotes_satanas              mazama_gouazoubira             
[165] didelphis_sp                    cebidae                        
[167] sylvilagus_brasiliensis         saimiri_sp                     
[169] alouatta_discolor               psophia_obscura                
[171] cebus_kaapori                   mico_leucippe                  
[173] procyonidae                     cf_crax_sp                     
[175] penelope_superciliaris          dasyprocta_iacki               
[177] callicebus_baptista             galliformes                    
[179] procyon_cancrivorus             tapirus_sp                     
[181] dasyprocta_azarae               cavia_sp                       
[183] didelphis_aurita                cripturellus_sp                
[185] sapajus_cay                     chrysocyon_brachyurus          
[187] galea_spixii                    leopardus_sp                   
[189] cebuella_pygmaea                cervidae                       
[191] cf_crax_globulosa               ptheciidae                     
[193] sciurillus_sp                   guerlinguetus_sp               
[195] brachyteles_arachnoides         alouatta_guariba_clamitans     
196 Levels: aburria_cujubi aburria_cumanensis ... urosciurus_spadiceus
# retornar as observaçÔes de uma UC fornecendo o nome
filtrar_dados(nome_sps = nomes_sps[1])
# retornar as observaçÔes de mais de uma UC
filtrar_dados(nome_sps = nomes_sps[c(33, 34)])

Para selecionar as observaçÔes de uma ou mais observaçÔes validadas, o(s) nível(is) taxonÎmico(s) deve(m) ser informados usando o argumento validacao_obs.

# retornar as observaçÔes de uma espécie fornecendo o nome
filtrar_dados(
  nome_sps = nomes_sps[c(33, 34)],
  validacao_obs = "especie"
)

Finalmente, também é possível selecionar as observaçÔes a partir da(s) Unidade(s) de Cosnervação, espécie(s) e nível(is) taxonÎmico(s) de validação.

# retornar as observaçÔes de uma espécie fornecendo o nome
filtrar_dados(
  nome_ucs = "flona_do_jamari",
  nome_sps = "callicebus_brunneus",
  validacao_obs = "especie"
)

2.3 Transformação dos dados

O uso da função que ajusta os modelos de função de detecção aos dados para estimativa de abundùncia e densidade das espécies exigem que os dados apresentem um formato específico. A função transformar_dados_formato_Dsitance() realiza a seleção das variåveis e as transformaçÔes necessårias para deixar os dados prontos para serem analisados.

Primeiramente, é necessårio criar um tabela de dados contendo as observaçÔes da espécie que se deseja estimar a densidade.

dasy_croc <- filtrar_dados(
  nome_sps = "dasyprocta_croconota",
  validacao_obs = "especie"
)
# transformar os dados para o formato do Distance
dasy_croc_com_rep <- transformar_dados_formato_Distance(dasy_croc)

dasy_croc_com_rep

A função tambĂ©m permite eliminar as amostragens repetidas realizadas em uma mesma estação do ano, selecionando apenas o dia em que foi registrado o maior nĂșmero de observaçÔes para uma determinada estação e ano. Para eliminar as amostragens repetidas, basta utilizar o argumento amostras_repetidas = FALSE.

dasy_croc_sem_rep <- transformar_dados_formato_Distance(
  dados = dasy_croc,
  amostras_repetidas = FALSE
)

dasy_croc_sem_rep

3 PARTE III – Explorando e selecionando os dados para as análises

Apresentamos abaixo um conjunto de ferramentas que permite diversas formas de explorar todo o conjunto de dados.

3.1 InformaçÔes Gerais sobre o Banco de Dados

3.1.1 Total Unidades de Conservação amostradas

# contar nĂșmero total de UC's 
n_ucs <- contar_n_uc()
n_ucs
[1] 40

Os dados são provenientes de 40 unidades de conservação ao todo.

3.1.2 NĂșmero de unidades de conservação amostradas em cada ano

Gerar função para tabela dinùmica.

gerar_tabdin(n_ucs_ano)

3.1.3 Unidades de conservação amostradas em um maior nĂșmero de anos

n_ano_uc <- contar_n_ano_uc()
n_ano_uc  

3.1.4 Total de observaçÔes por Unidade de Conservação

# contar nĂșmero de observaçÔes por UC
n_obs_uc <- contar_n_obs_uc()
n_obs_uc
# gerar tabdin
gerar_tabdin(n_obs_uc)
# gerar tabdin
gerar_tabdin(n_obs_uc)
# plotar o nĂșmero de observaçÔes por UC
plotar_n_obs_uc_interativo(n_obs_uc)

3.1.5 NĂșmero de observaçÔes realizadas por UC em cada ano

n_obs_uc_ano <- contar_n_obs_uc_ano()
n_obs_uc_ano

Tabela interativa para consultar quantas observaçÔes foram realizadas por ano em cada UC

gerar_tabdin(n_obs_uc_ano)

3.1.6 Total de observaçÔes validadas por nível taxonÎmico

Essas operaçÔes são realizadas sobre a tabela de dados dados_completos pois os dados que foram transformados para o formato do distace no R não possuem a coluna validation, necessåria para essas opereaçÔes. Mais a frente o procedimento de como obter os dados selecionados e transformatos para o formato das anålises serå demonstrado.

# contar observaçÔes validadas ao nível de espécie
n_obs_validadas <- contar_n_obs_validadas()
n_obs_validadas
Foram selecionadas apenas as observaçÔes validadas ao nível de espécie, somando um total

observaçÔes.

# gerar grĂĄfico com nĂșmero observaçÔes validadas para cada nĂ­vel taxonĂŽmico
plotar_n_obs_validadas_interativo(n_obs_validadas)

3.1.7 Total de espécies registradas

n_sp <- contar_n_sp()
n_sp
[1] 196

Até aqui temos dados para 196 espécies.

##SuficĂȘncia Amostral

NĂșmero de observaçÔes

Para que o mĂ©todo de anĂĄlise por distĂąncia possa ser utilizado para estimativas baseadas em modelos, sĂŁo recomendadas quantidades mĂ­nimas de observaçÔes e de transectos (Unidades Amostrais). Segundo BUCKLAND et. al. (2015), O nĂșmero mĂ­nimo sugerido de animais ou grupos Ă© de 60 – 80 animais (ou grupos) quando a amostragem Ă© feita pelo mĂ©todo dos transectos lineares. É possĂ­vel utilizar nĂșmeros menores que estes para realizar as anĂĄlises, porĂ©m deve-se ter o cuidado de verificar se as funçÔes de detecção estĂŁo bem modeladas. Estes nĂșmeros recomendados se aplicam a cada função de detecção a ser modelada. Assim, quando se pretende estratificar os dados, dividindo-os em subconjuntos, seja por regiĂŁo geogrĂĄfica, seja por perĂ­odo amostral, Ă© necessĂĄrio ter um cuidado para que a suficiĂȘncia amostral se mantenha dentro dos subconjuntos.

Réplicas e repetiçÔes

O nĂșmero mĂ­nimo de rĂ©plicas para os transectos deve ser de 10-20, o que deve aumentar para espĂ©cies cujas populaçÔes sĂŁo distribuĂ­das em manchas BUCKLAND et. al. (2015). O nĂșmero de rĂ©plicas reais para cada espĂ©cie Ă© o nĂșmero de transectos, que recebem os nomes das estaçÔes amostrais em cada Unidade de conservaçaĂ”.

Um outro aspecto que Ă© necessĂĄrio observar Ă© o nĂșmero de repetiçÔes, que terĂĄ impacto tanto sobre o esforço quanto sobre a suficiĂȘncia amostral. Uma das limitaçÔes dos dados do Programa Monitora Ă© o pequeno nĂșmero de rĂ©plicas por Unidade de Conservação e muitas repetiçÔes para as mesmas estaçÔes amostrais. O excesso de repetiçÔes, especialmente em um mesmo perĂ­odo amostral, compromete a premissa de independĂȘncia entre as observaçÔes. AlĂ©m disso, acaba tendo um efeito de inflar o esforço amostral e a ĂĄrea coberta pela amostragem, o que prejudica as estimativas de densidade.

Apenas para ilustar, para os dados da cutia Dasyprocta croconota da Resex TapajĂłs-Arapinuns, a Estação Amostral Boim foi percorrida durante 70 dias de amostragem. Isso significa que ajustando o comprimento do transecto de 5 km pelo nĂșmero de repetiçÔes, o esforço amostral passou para 350 km. A ĂĄrea coberta aumentou em 70x, o que terĂĄ consequĂȘncias sobre a estimativa densidade, que tenderĂĄ a ser subestimada. AlĂ©m disso, o coeficiente de variação das estimativas de taxa de encontro, abundĂąncia e densidade tambĂ©m tenderĂŁo a aumentar pelo efeito da variaçÔes temporais entre as amostragens.

Para lidar com o excesso de repetiçÔes, implementamos um fluxo de trabalho onde reduzimos o nĂșmero de repetiçÔes, mantendo somente um dia de amostragem com o maior nĂșmero de observaçÔes para cada perĂ­odo amostral (Parte V, Fluxo 2).

3.1.7.1 NĂșmero total de observaçÔes por espĂ©cie

# contar total sp
n_obs_sp <- contar_n_obs_sp()
n_obs_sp
# gerar tabela dinĂąmica com o nĂșmero total de obsevaçÔes por espĂ©cie
gerar_tabdin(n_obs_sp)
# plotar o o nĂșmero de observaçÔes por UC
plotar_n_obs_sp_interativo(n_obs_sp)

3.1.7.2 NĂșmero de observaçÔes para cada espĂ©cie por unidade de conservação

# gerar tabela com o nĂșmero de observaçÔes por espĂ©cie e por UC
n_obs_sp_uc <- contar_n_obs_sp_uc()
n_obs_sp_uc
gerar_tabdin(n_obs_sp_uc)

3.1.7.3 NĂșmero de observaçÔes para cada espĂ©cies por ano

n_obs_sp_ano <- contar_n_obs_sp_ano()
n_obs_sp_ano

Tabela interativa para consultar quantas observaçÔes foram realizadas para cada espécie em cada ano

gerar_tabdin(n_obs_sp_ano)

3.1.7.4 NĂșmero de observaçÔes para cada espĂ©cies por UC e por ano

n_obs_sp_uc_ano <- contar_n_obs_sp_uc_ano()
n_obs_sp_uc_ano

Tabela interativa para consultar quantas observaçÔes foram realizadas para cada espécie em cada ano

gerar_tabdin(n_obs_sp_uc_ano)

3.1.7.5 NĂșmero de observaçÔes para cada espĂ©cies por UC, por estação do ano e por ano

n_obs_sp_uc_estacao_ano <- contar_n_obs_sp_uc_estacao_ano()
n_obs_sp_uc_estacao_ano
gerar_tabdin(n_obs_sp_uc_estacao_ano)

###INCLUIR Réplicas e RepetiçÔes

3.1.7.6 NĂșmero de UCs para cada espĂ©cie

3.1.7.7 NĂșmero de rĂ©plicas (estaçÔes amostrais) para cada espĂ©cie

3.1.7.8 NĂșmero de rĂ©plicas (estaçÔes amostrais) para cada espĂ©cie por UC

####NĂșmero de repetiçÔes por estação amostral para cada espĂ©cie

####NĂșmero de repetiçÔes por estação amostral por UC para cada espĂ©cie

####NĂșmero de repetiçÔes por estação amostral por UC para cada espĂ©cie por ano

####NĂșmero de repetiçÔes por estação amostral por UC para cada espĂ©cie por perĂ­od amostral (estaçÔes do ano/ano)

3.2 Distribuição das frequĂȘncias de observaçÔes pela distĂąncia

Algumas situaçÔes amostrais podem levar a efeitos indesejados na distribuição dos dados, comentadas a seguir. Para explorar a distribuição dos dados recomendamos também o uso do app_distanca_interativo.R em piper3d_monitora_florestal\apps.

Empilhamento das observaçÔes (heaping) – ocorre quando valores das distĂąncias perpendiculares sĂŁo arredondados. O efeito Ă© um acĂșmulo de observaçÔes sobre a mesma distĂąncia, que corresponde a um valor redondo. Um tipo especĂ­fico de empilhamento Ă© quando ele se dĂĄ sobre a distĂąncia zero, tambĂ©m chamado de pico prĂłximo a distĂąncia zero (spike near zero distance). Esse tipo de efeito foi observado com frequĂȘncia nos dados do Programa Monitora. Uma das estratĂ©gias para redução dos efeitos de empilhamento Ă© agrupar os dados de distĂąncia em intervalos. Implementamos essa estratĂ©gia na Parte V – Fluxo 3.

Movimento de resposta ao observador – os animais podem ser repelidos ou atraĂ­dos pelo observador. Para animais que apresentam resposta de fuga em relação ao observador o efeito no histograma de frequĂȘncias Ă© um aumento nas observaçÔes em distĂąncias intermediĂĄrias. Para animais que sĂŁo atraĂ­dos pelo observador, a tendĂȘncia Ă© de um aumento nas observaçÔes nas distĂąncias prĂłximas a zero, o que tambĂ©m pode gerar o padrĂŁo de pico prĂłximo a zero. O efeito desse viĂ©s sobre as observaçÔes Ă© enviesar tambĂ©m os modelos ajustados (formato da curva), as probabilidades de deteção e abundĂąncias estimadas em cada faixa de distĂąncia.

SuperdispersĂŁo – Ă© um efeito causado quando as observaçÔes nĂŁo sĂŁo independentes, como no caso das repetiçÔes em um mesmo transecto. O efeito no histograma sĂŁo picos em algumas distĂąncias ou reduçÔes abruptas em outras (Figura X). O excesso de repetiçÔes tambĂ©m foi uma limitação encontrada nos dados do Programa Monitora. Implementamos uma estratĂ©gia para reduzir o nĂșmero de repetiçÔes mantendo somente a data com o maior nĂșmero de observaçÔes por perĂ­odo amostral na Parte V - Fluxo 2.

Para maiores detalhes, ver figuras no Material de Suporte de Aspectos TeĂłricos.

# gerar o gråfico exploratório da distribuição de distùncias perpendiculares para a espécies Dasyrocta croconota na Resex Tapajós-Arapiuns
fig <- dados_filtrados |>
  # excluir NA's da variĂĄvel distance
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo()

fig

3.3 INCLUIR Distriubuição das covariåveis pela distùncia

Uma boa escolha de covariĂĄveis passa por um bom processo exploratĂłrio dos dados. É importante avaliar como fatores ambientais ou amostrais podem influenciar de forma significativa a detectabilidade dos animais. Para avaliar esse possĂ­vel efeito, Ă© necessĂĄrio olhar a distribuição das covariĂĄveis em relação Ă  distĂąncia. Se houver viĂ©s das covariĂĄveis em relação ĂĄ distĂąncia, Ă© possĂ­vel que estejam influenciando na detectabilidade tambĂ©m. Por exemplo, se a atividade de um animal Ă© influenciada pelo horĂĄrio, Ă© possĂ­vel que ele seja detectado com maior frequĂȘncia em distĂŁncias maiores no seu horĂĄrio de maior atividade.

Para os dados do Programa Monitora, uma das principais covariĂĄveis a ser considerada Ă© o tamanho do grupo (s, que deve ser chamada de size para o pacote Distance). Um dos efeitos esperados para espĂ©cies que formam grupos Ă© o chamado viĂ©s de tamanho. A tendĂȘncia Ă© que a pequenas distĂąncias todos os grupos sejam detectĂĄveis, mas somente os grupos maiores serĂŁo detectados a distĂąncias maiores.

4 PARTE IV – Ajustando os modelos

4.1 Fluxo de anĂĄlise dos dados:

A seguir, apresentamos o fluxo de anĂĄlise dos dados que envolve a fase exploratĂłria, truncamento, ajuste e avaliação de modelos e estimativas de abundĂąncia e densidade para as espĂ©cies que selecionamos como modelo. Usamos como critĂ©rios de seleção tanto o nĂșmero de observaçÔes por Unidade de Conservação quanto a distribuição das frequĂȘncias de observação, nos casos em que isso foi possĂ­vel. De forma geral, as espĂ©cies com nĂșmero satisfatĂłrio de observaçÔes ($>$60), apresentaram pico de observaçÔes prĂłximos a zero.

NĂłs usamos como modelo para este fluxo os dados da cutia Dasyprocta croconota coletados na Resex TapajĂłs-Arapiuns entre 2014 e 2021, pelo grande nĂșmero de observaçÔes para uma mesma UC. Os dados de distĂąncias perpendiculares para essa espĂ©cie apresentam trĂȘs caracterĂ­sticas indesejadas: nĂșmero excessivo de repetiçÔes amostrais numa mesma estação amostral, pico de distĂąncias prĂłximo a zero e empilhamento de observaçÔes em uma mesma distĂąncia.

Para lidar com as repetiçÔes, testamos a anĂĄlise dos dados com todas as repetiçÔes e com o nĂșmero de repetiçÔes reduzidas. Para lidar com os picos de distĂąncia prĂłximos a zero, testamos o uso dos dados com distĂąncias exatas e distĂąncias agrupadas. Essas estratĂ©gias estĂŁo descritas nos Fluxos 1-3. No primeiro fluxo, comentamos tambĂ©m as escolhas feitas e os resultados obtidos. Os demais fluxos sĂŁo repetiçÔes deste primeiro fluxo, porĂ©m com mudança na estrutura dos dados.

5 REVISAR ESSE trecho no final

EspĂ©cies com maior nĂșmero de observaçÔes/UC possibilitam testar, posteriormente, estratificaçÔes nos dados, preservando um nĂșmero de observaçÔes satisfatĂłrio dentro dos estratos. Por isso, começamos apresentando um fluxo completo de anĂĄlise, incluindo Amostragem por DistĂąncia Convencional, Amostragem por DistĂąncia com MĂșltiplas CovariĂĄveis e Amostragem por DistĂąncia com Estratificação nos dados com as espĂ©cies com maior nĂșmero de observaçÔes. Por isso, selecionamos como modelo a espĂ©cie com o maior nĂșmero de observaçÔes para uma mesma UC e a terceira com o maior nĂșmero total de observaçÔes.

5.1 Espécie Modelo - Dasyprocta croconota - Resex Tapajós Arapiuns

Fonte: biolib.cz
Fonte: biolib.cz

Essa Ă© a espĂ©cie com o maior nĂșmero de observaçÔes para uma mesma UC. Apresentou, como a maioria das espĂ©cies em diferentes UCs, um pico de observaçÔes prĂłximo a dsitĂąncia zero. TambĂ©m apresentou efeito de empilhamento sobre as distĂąncias 5, 10, 15 e 20m, indicando que os dados foram arrendondados para essas distĂąncias.

5.1.1 Obter os dados para as anĂĄlises

É possĂ­vel obter as observaçÔes da espĂ©cie e Unidade de Conservação de interesse e tornĂĄ-las analisĂĄveis pelo pacote Distance utilizando duas funçÔes: filtrar_dados() e transformar_dados_formato_Distance(). A primeira filtra a base de dados original a partir da espĂ©cie e UC desejada eplos argumentos nome_sps e nome_ucs, enquanto a segunda transforma os dados para o formato do pacote Distance.

# carregar dados
cutia_tap_arap <- filtrar_dados(
  nome_ucs = "resex_tapajos_arapiuns",
  nome_sps = "dasyprocta_croconota"
) |> 
  transformar_dados_formato_Distance()

cutia_tap_arap

5.1.2 Amostragem por DistĂąncia Convencional

5.1.2.1 Fluxo 1 - Distùncias exatas com todas as repetiçÔes

5.1.2.1.1 Plotando o histograma das frequĂȘncias de observaçÔes pela distĂąncia

O histograma interativo estĂĄ disponĂ­vel no aplicativo em Shiny app_distancia_interativo.R em piper3d_monitora_florestal\apps.

A distribuição dos dados no histograma permite observar um pico de observaçÔes prĂłximo a zero, assim como picos de observação em 5, 10, 15 e 20m, alĂ©m de uma considerĂĄvel perda em detectabilidade a partir dos 20m. É possĂ­vel alterar a binagem dos histogramas atravĂ©s do argumento largura_caixa. Neste exemplo ajustamos para 1, o que facilita a observação de picos de detecação e efeitos de heaping nos dados.

cutia_tap_arap |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)

Para eliminar as observaçÔes feitas a distùncias com baixa detectabilidade, vamos testar diferentes proporçÔes de truncamento.

5.1.2.1.2 Testando distĂąncia de truncamento (w)

Vamos explorar diferentes distùncias de truncamento para um mesmo modelo de função chave com distribuição half-normal. Optamos por truncar os dados pela percentagem para padronizar a rotina para diferentes espécies. Buckland et al. (2001) sugere um corte entre 5-10% das observaçÔes detectadas nas maiores distùncias. Vamos selecionar o valor de corte pelo modelo com melhor ajuste utilizando a função selecionar_distancia_truncamento(). Para automatizar a avaliação da truncagem para qualquer conjunto de dados, implementamos no código o teste para as seguintes proporçÔes de corte: 5, 10, 15, 20 e 25% das observaçÔes mais distantes. Contudo, os valores de corte podem ser alterados pelo usuårio fornecendo uma lista com novos valores ao argumento dist_truncamento. A função gera uma tabela comparando os modelos e também plotamos os gråficos dos modelos ajustados para os dados truncados usando a função plotar_.

5.1.2.1.2.1 Tabela com resumo comparativo dos modelos
# conduz a selecao da melhor distancia de truncamento a partir do ajsute de modelos com funcao de deteccao half-normal sem termos de ajuste
cutia_tap_arap_dist_trunc <- cutia_tap_arap |> 
  selecionar_distancia_truncamento()
Fitting half-normal key function
AIC= 4676.418
Fitting half-normal key function
AIC= 5354.545
Fitting half-normal key function
AIC= 5791.182
Fitting half-normal key function
AIC= 6375.771
Fitting half-normal key function
AIC= 7212.428
cutia_tap_arap_dist_trunc$selecao

Os critĂ©rios de ajuste dos modelos servem aqui como uma informação complementar, mas nĂŁo serĂŁo decisivos na escolha da distĂąncia de truncamento. Naturalmente, eliminando os dados das distĂŁncias de menor detectabilidade, os modelos tendem a ter um melhor ajuste pela menor variabilidade dos dados. AlĂ©m disso, nesse caso os valores de deltaAIC serĂŁo sempre zero, pois nĂŁo Ă© possĂ­vel comparar valores de AIC para conjuntos de dados diferentes (nesse caso os dados diferem em nĂșmero de observaçÔes).

5.1.2.1.2.2 Plotando o histograma com os dados truncados.

Histogramas resultantes dos modelos, com todas as distùncias de truncagem, para auxiliar na seleção da melhor distãncia.

plotar_funcao_deteccao_selecao_distancia_truncamento(cutia_tap_arap_dist_trunc)

$`25%`
NULL

$`20%`
NULL

$`15%`
NULL

$`10%`
NULL

$`5%`
NULL

ApĂłs avaliar tanto o ajuste dos modelos quanto os grĂĄficos, optamos por truncar 10% das observaçÔes feitas nas maiores distĂąncias. Apesar dos melhores valores de AIC e de ajuste do CramĂ©r-von Mises para 25%, os histogramas com modelos ajustados para 25%, 20% e 15% apresentaram modelos quase lineares e com uma grande probabilidade de deteção nos Ășltimos intervalos de distĂąncia. O modelo com corte de 10% apresentou uma curva decrescente e nĂŁo tendeu a zero nas Ășltimas distĂąncias. JĂĄ no modelos para 5% as funçÔes de deteção tendem a zero nos Ășltimos intervalos de distĂąncia. O corte de 10% das observaçÔes mais distantes resultou em uma distĂąncia de truncamento de 15m.

5.1.2.1.3 Ajustando diferentes modelos de funçÔes de detecção

As funçÔes de detecção são ajustadas através da função ds() no pacote Distence para o R. Para otimizar o fluxo de ajuste de diferentes modelos de função de detecção, empacotamos as diferentes combinaçÔes de funçÔes chave (uniforme, half-normal e hazard-rate) e termos de ajustes (cosseno, polinomial simples e polinomial de Hermite) na função ajustar_modelos_distance().

Para definir a distĂąncia de truncamento dos dados Ă© necessĂĄrio fornecer o argumento truncamento, que pode ser definido tanto em percentagem de corte dos dados quanto em valor de distĂŁncia.

5.1.2.1.3.1 Uniforme com termos de ajuste Cosseno e polinomial simples
# ajustando a função de detecção uniforme para um truncamento de 10% dos dados
cutia_tap_arap_unif <- cutia_tap_arap |> 
  ajustar_modelos_Distance(
    funcao_chave = "unif",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 6586.595
Fitting uniform key function with cosine(1) adjustments
AIC= 6363.157
Fitting uniform key function with cosine(1,2) adjustments
AIC= 6357.69
Fitting uniform key function with cosine(1,2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6328.133
Fitting uniform key function with cosine(1,2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6295.384
Fitting uniform key function with cosine(1,2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6288.133
Warning: Detection function is not strictly monotonic!Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 6586.595
Fitting uniform key function with simple polynomial(2) adjustments
AIC= 6410.42
Fitting uniform key function with simple polynomial(2,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6367.003
Fitting uniform key function with simple polynomial(2,4,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6363.953
Fitting uniform key function with simple polynomial(2,4,6,8) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6364.18

Uniform key function with simple polynomial(2,4,6) adjustments selected.
Warning: Detection function is not strictly monotonic!

Dentre as combinaçÔes de termos de ajustes para a função chave de distribuição uniforme, o Distance selecionou o modelo uniforme com ajuste polinomial simples, com as ordens 2, 4 e 6. Ele mantĂ©m esse modelo, e descarta os demais. Os Warnings indicando que a função de detecção nĂŁo Ă© estritamente monotĂŽnica avisam que os dados nĂŁo foram constrangidos para a monotonicidade. Isso porque o uso de termos de ajustes, especialmente de ordens acima de 2, podem levar Ă  perda da monotonidade (a curva pode se tornar crescente em algum momento, o que nĂŁo Ă© desejado). É preciso avaliar se a falta desse constragimento levou efetivamente Ă  perda da monotonicidade ao olhar os grĂĄficos de ajuste dos modelos.

5.1.2.1.3.2 Half-Normal sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_tap_arap_hn <- cutia_tap_arap |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = "10%")
Fitting half-normal key function
AIC= 6375.771
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 6375.771
Fitting half-normal key function with cosine(2) adjustments
AIC= 6349.7
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6321.849
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6293.72
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6282.535
Fitting half-normal key function with cosine(2,3,4,5,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6220.852
Warning: Detection function is not strictly monotonic!Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 6375.771
Fitting half-normal key function with Hermite(4) adjustments
AIC= 6377.362

Half-normal key function selected.

Neste caso, o modelo selecionado pelo Distance foi o Half-normal sem nenhum termo de ajuste.

5.1.2.1.3.3 Hazard-rate sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção hazard-rate para um truncamento de 10% dos dados
cutia_tap_arap_hr <- cutia_tap_arap |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = "10%")
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 6048.452
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 6048.452
Fitting hazard-rate key function with cosine(2) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 6048.452
Fitting hazard-rate key function with simple polynomial(4) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).

Aqui o melhor modelo selecionado pelo Distance foi o Hazard-rate sem os termos de ajuste. Nesse caso, também hå um warning para o problema na distribuição dos dados, que apresentam um pico próximo a distùncia zero e não são bem ajustados pelo modelo hazard-hate.

5.1.2.1.4 Comparando os modelos

Para comparar os modelos Ă© preciso avaliar trĂȘs critĂ©rios: AIC, ajuste e forma das funçÔes nos grĂĄficos e bondade de ajuste. O pacote Distance possui a função summarize_ds_models que gera uma tabela com os modelos para comparação de alguns parĂąmetros: a primeira coluna Model, indica as funçÔes chaves e respectivos termos de ajuste; a coluna Formula apresenta as covariĂĄveis, quando incluĂ­das no modelo, ou ~ 1, quando nĂŁo hĂĄ covariĂĄveis; C-vM p-value vai apresentar os valores de p para o teste de bondade de ajuste de CramĂ©r-von Mises; \(\hat{P_a}\) apresenta a probalidade de deteção global estimada para cada modelo; se(\(\hat{P_a}\)) apresenta o erro padrĂŁo para as estimativas de probabilidade de detecção; e \(\Delta\)AIC apresenta os valores de diferença entre os AIC’s de modelos subsequentes.

5.1.2.1.4.1 Tabela com o resumo comparativo dos modelos
fluxo1_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(
  cutia_tap_arap_hn$`Sem termo`,
  cutia_tap_arap_hn$Cosseno,
  cutia_tap_arap_hn$`Hermite polinomial`,
  cutia_tap_arap_hr$`Sem termo`,
  cutia_tap_arap_hr$Cosseno,
  cutia_tap_arap_hr$`Polinomial simples`,
  cutia_tap_arap_unif$Cosseno,
  cutia_tap_arap_unif$`Polinomial simples`
)

fluxo1_selecao_funcao_deteccao_termo_ajuste

Dentre os modelos testados, o que apresentou melhor valor de ajuste e AIC foi o hazard-rate. O ajuste do Cramér-von Mises foi consideravelmente maior que os demais (para esse tipo de teste, quanto maior o valor de p, melhor o ajuste), assim como as diferenças no delta AIC foram bastante elevadas.

5.1.2.1.4.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
# gerar uma lista com os modelos selecionados ordenados do melhor para o pior modelo
fluxo1_modelos_selecionados <- gerar_lista_modelos_selecionados(
  cutia_tap_arap_hr$`Sem termo`,
  cutia_tap_arap_unif$`Cosseno`,
  cutia_tap_arap_hn$`Cosseno`,
  cutia_tap_arap_unif$`Polinomial simples`,
  cutia_tap_arap_hn$`Sem termo`, 
  nome_modelos_selecionados = fluxo1_selecao_funcao_deteccao_termo_ajuste
)

# plotar a probabilidade de detecção observada (barras) e a esperada (linhas e pontos)
plotar_funcao_deteccao_modelos_selecionados(fluxo1_modelos_selecionados)

$`Hazard-rate`
NULL

$`Half-normal with cosine adjustment terms of order 2,3,4,5,6`
NULL

$`Uniform with cosine adjustment terms of order 1,2,3,4,5`
NULL

$`Uniform with simple polynomial adjustment terms of order 2,4,6`
NULL

$`Half-normal`
NULL

Olhando para os histogramas com modelos ajustados, Ă© possĂ­vel observar o efeito do acĂșmulo de observaçÔes prĂłximo a zero. O modelo com a função chave hazard-hate sem termos de ajuste, apesar de ter apresentado o melhor valor de ajuste pelo CramĂ©r-von Mises e o melhor valor de AIC, apresentou dois problemas. As probalidades de deteção estimadas por intevalo de distĂąncia (barras verdes), ficaram muito baixas. AlĂ©m disso, a curva da função de deteção apresenta pico na distĂąncia prĂłxima a zero, decaindo rapidamente e se aproximando de zero ao longo do eixo das distĂŁncias. Todos os outros quatro modelos tiveram ajuste e AIC bastante inferiores ao hazard-hate. Entretanto as curvas estĂŁo relativamente melhores. As curvas do segundo e terceiro modelo, uniforme com ajuste cosseno e half-normal com ajuste cosseno, respectivamente, tendem Ă  perda de monotonicidade. As duas Ășltimas curvas, para os modelos uniforme com ajuste polinomial simples e half-normal sem ajuste, nĂŁo perdem a monotonicidade. De forma geral, as probabilidades de detecção nĂŁo tĂȘm um bom ajuste abaixo da curva, e nĂŁo apresentam um decaimento gradual com a distĂąncia. Esses sĂŁo problemas inerentes Ă  distribuição dos dados.

5.1.2.1.4.3 Teste de bondade de ajuste dos modelos e Q-Q plots
bondade_ajuste_fluxo1 <- testar_bondade_ajuste(
  fluxo1_modelos_selecionados, 
  plot = TRUE,
  chisq = TRUE, 
  intervalos_distancia  =  NULL
)


bondade_ajuste_fluxo1

Aqui são gerados Q-Q plots que permitem avaliar a qualidade do ajuste dos modelos. E também uma tabela com os resultados do Carmér-von Mises, onde W é o valor do teste e p seu valor de significùncia. Nesse caso, quanto maior o valor de p, melhor o ajuste do modelo.

5.1.2.1.5 Avaliando as estimativas de AbundĂąncia e Densidade

Aqui, sĂŁo resumidos os dados de taxa de encontro, abundĂąncia e densidade em trĂȘs tabelas.

5.1.2.1.5.1 CaracterĂ­sticas da ĂĄrea de estudo e da taxa de encontro
5.1.2.1.5.2 Características de abundùncia, esforço e detecção
# gerar resultados abundùncia e detecção
fluxo1_caracteristicas_esforco_abundancia_deteccao <- gerar_resultados_Distance(
  dados = fluxo1_modelos_selecionados,
  resultado_selecao_modelos = fluxo1_selecao_funcao_deteccao_termo_ajuste,
  tipo_de_resultado = "abundancia", 
  estratificacao = FALSE
)

fluxo1_caracteristicas_esforco_abundancia_deteccao
5.1.2.1.5.3 CaracterĂ­sticas de densidade
# gerar resultados densidade e coeficiente de variação
fluxo1_caracteristicas_densidade <- gerar_resultados_Distance(
  dados = fluxo1_modelos_selecionados,
  resultado_selecao_modelos = fluxo1_selecao_funcao_deteccao_termo_ajuste,
  tipo_de_resultado = "densidade", 
  estratificacao = FALSE
)

fluxo1_caracteristicas_densidade

5.1.2.2 Fluxo 2 - Distùncias exatas sem repetiçÔes

5.1.2.2.1 Filtrando os dados para eliminar as repetiçÔes
cutia_tap_arap_sem_repeticao <- filtrar_dados(
  nome_ucs = "resex_tapajos_arapiuns",
  nome_sps = "dasyprocta_croconota", 
  validacao_obs = "especie"
) |> 
  transformar_dados_formato_Distance(amostras_repetidas = FALSE)

cutia_tap_arap_sem_repeticao
5.1.2.2.2 Plotando o histograma das frequĂȘncias de observaçÔes pela distĂąncia
cutia_tap_arap_sem_repeticao |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
5.1.2.2.3 Testando distĂąncia de truncamento (w)
5.1.2.2.3.1 Tabela com resumo comparativo dos modelos
# conduz a selecao da melhor distancia de truncamento a partir do ajsute de modelos com funcao de deteccao half-normal sem termos de ajuste
cutia_tap_arap_sem_repeticao_dist_trunc <- cutia_tap_arap_sem_repeticao |> 
  selecionar_distancia_truncamento()
Fitting half-normal key function
AIC= 190.812
Fitting half-normal key function
AIC= 200.849
Fitting half-normal key function
AIC= 232.199
Fitting half-normal key function
AIC= 271.27
Fitting half-normal key function
AIC= 275.398
cutia_tap_arap_sem_repeticao_dist_trunc$selecao
5.1.2.2.3.2 Plotando o histograma com os dados truncados.
plotar_funcao_deteccao_selecao_distancia_truncamento(cutia_tap_arap_sem_repeticao_dist_trunc)

$`25%`
NULL

$`20%`
NULL

$`15%`
NULL

$`10%`
NULL

$`5%`
NULL

5.1.2.2.4 Ajustando diferentes modelos de funçÔes de detecção
5.1.2.2.4.1 Uniforme + Cosseno
# ajustando a função de detecção uniforme para um truncamento de 10% dos dados
cutia_tap_arap_sem_repeticao_unif <- cutia_tap_arap_sem_repeticao |> 
  ajustar_modelos_Distance(
    funcao_chave = "unif", 
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 270.805
Fitting uniform key function with cosine(1) adjustments
AIC= 270.793
Fitting uniform key function with cosine(1,2) adjustments
AIC= 272.786

Uniform key function with cosine(1) adjustments selected.
5.1.2.2.4.2 Half-Normal sem termos de ajuste e com termos de ajuste
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_tap_arap_sem_repeticao_hn <- cutia_tap_arap_sem_repeticao |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = "10%")
Fitting half-normal key function
AIC= 271.27
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 271.27
Fitting half-normal key function with cosine(2) adjustments
AIC= 273.177

Half-normal key function selected.
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 271.27
Fitting half-normal key function with Hermite(4) adjustments
AIC= 273.247

Half-normal key function selected.
5.1.2.2.4.3 Hazard-rate sem termos de ajuste e com termos de ajuste
# ajustando a função de detecção hazard-rate para um truncamento de 10% dos dados
cutia_tap_arap_sem_repeticao_hr <- cutia_tap_arap_sem_repeticao |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = "10%")
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 273.379
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 273.379
Fitting hazard-rate key function with cosine(2) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 275.348

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 273.379
Fitting hazard-rate key function with simple polynomial(4) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 277.333

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).
5.1.2.2.5 Comparando os modelos
5.1.2.2.5.1 Tabela com o resumo comparativo dos modelos
fluxo2_lista_modelos_ajustados <- list(
  cutia_tap_arap_sem_repeticao_hn, 
  cutia_tap_arap_sem_repeticao_hr, 
  cutia_tap_arap_sem_repeticao_unif
)

fluxo2_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(
  cutia_tap_arap_sem_repeticao_hn$`Sem termo`,
  cutia_tap_arap_sem_repeticao_hn$Cosseno,
  cutia_tap_arap_sem_repeticao_hn$`Hermite polinomial`,
  cutia_tap_arap_sem_repeticao_hr$`Sem termo`, 
  cutia_tap_arap_sem_repeticao_hr$Cosseno, 
  cutia_tap_arap_sem_repeticao_hr$`Polinomial simples`,
  cutia_tap_arap_sem_repeticao_unif
)

fluxo2_selecao_funcao_deteccao_termo_ajuste
5.1.2.2.5.2 Gråficos de ajuste das funçÔes de detecção às probabilidades de detecção

# plotar a probabilidade de detecção observada (barras) e a esperada (linhas e pontos)
plotar_funcao_deteccao_modelos_selecionados(fluxo2_modelos_selecionados)
$`Uniform with cosine adjustment term of order 1`
NULL

$`Half-normal`
NULL

$`Hazard-rate`
NULL

5.1.2.2.5.3 Teste de bondade de ajuste dos modelos e Q-Q plots
bondade_ajuste_fluxo2 <- testar_bondade_ajuste(
  fluxo2_modelos_selecionados, 
  plot = TRUE,
  chisq = TRUE, 
  intervalos_distancia  =  NULL
)


bondade_ajuste_fluxo2
5.1.2.2.6 Avaliando as estimativas de AbundĂąncia e Densidade
5.1.2.2.6.1 CaracterĂ­sticas da ĂĄrea de estudo e da taxa de encontro
# gera resultados ĂĄrea de estudo e taxa de encontro
fluxo2_caracteristicas_area_estudo_taxa_encontro <- gerar_resultados_Distance(
  dados = fluxo2_modelos_selecionados,
  resultado_selecao_modelos = fluxo2_selecao_funcao_deteccao_termo_ajuste,
  tipo_de_resultado = "area_estudo", 
  estratificacao = FALSE
)

fluxo2_caracteristicas_area_estudo_taxa_encontro
5.1.2.2.6.2 Características de abundùncia, esforço e detecção
5.1.2.2.6.3 CaracterĂ­sticas de densidade

5.1.2.3 Fluxo 3 - Distùncias agrupadas com todas as repetiçÔes

Aqui vamos partir do mesmo conjunto de dados do Fluxo 1 (cutia_tap_arap), com todas as repetiçÔes, mas vamos agrupar as distùncias em intervalos. Vamos usar o mesmo valor de truncamento, removendo 10% das observaçÔes nas maiores distùncias, o que significa que aproveitaremos as observaçÔes feitas até 15m de distùncia do observador.

5.1.2.3.1 Plotando o histograma das frequĂȘncias de observaçÔes pela distĂąncia

O histograma interativo estĂĄ disponĂ­vel no aplicativo em Shiny app_distancia_interativo.Rem piper3d_monitora_florestal\apps.

Aqui, plotamos quatro histogramas com binagens diferentes, para observar o efeito de agrupar os dados sobre as distribuiçÔes das frequĂȘncias de observaçÔes nos histogramas.

cutia_tap_arap |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
cutia_tap_arap |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 2)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
cutia_tap_arap |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 3)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
cutia_tap_arap |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 5)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
5.1.2.3.2 Definindo os intevalos de distĂąncia de agrupamento

É importante ressaltar que o valor máximo para categorização dos dados não deve utltrapassar o valor de truncagem. Caso contrário, não será possível ajustar os modelos aos dados.

5.1.2.3.2.1 Primeira binagem - Intervalos iguais de 1.5m
cutia_tap_arap_bin1 <- cutia_tap_arap |> 
  definir_intervalos_distancia(
    intervalos_distancia = seq(
      from = 0,
      to = 15,
      by = 1.5
      )
  )
Warning: Some distances were outside bins and have been removed.
5.1.2.3.2.2 Segunda binagem - Primeiro intervalo de 1m e demais intervalos de 1.4m
cutia_tap_arap_bin2 <- cutia_tap_arap |> 
  definir_intervalos_distancia(
    intervalos_distancia = c(
      0,
      seq(
      from = 1,
      to = 15,
      by = 1.4
      )
    )
  )
Warning: Some distances were outside bins and have been removed.
  
5.1.2.3.2.3 Terceira binagem - Intervalos iguais de 2.5m
cutia_tap_arap_bin3 <- cutia_tap_arap |> 
  definir_intervalos_distancia(
    intervalos_distancia = seq(
      from = 0,
      to = 15,
      by = 2.5
      )
  )
Warning: Some distances were outside bins and have been removed.
5.1.2.3.3 Ajustando diferentes modelos de funçÔes de detecção
5.1.2.3.3.1 Uniforme + Cosseno

Primeira Binagem

Aqui, por conta da binagem, o truncamento deve ser expresso em distùncia. Para os dados que estamos trabalhando, o corte de 10% das observaçÔes mais distantes truncam os dados em 15m.

cutia_tap_arap_bin1_unif <- cutia_tap_arap_bin1 |> 
  ajustar_modelos_Distance(
    funcao_chave = "unif",
    termos_ajuste = "cos",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 5507.784
Fitting uniform key function with cosine(1) adjustments
AIC= 5294.147
Fitting uniform key function with cosine(1,2) adjustments
AIC= 5290.028
Fitting uniform key function with cosine(1,2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5257.803
Fitting uniform key function with cosine(1,2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5237.861
Fitting uniform key function with cosine(1,2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5239.783

Uniform key function with cosine(1,2,3,4) adjustments selected.
Warning: Detection function is not strictly monotonic!

Segunda binagem


cutia_tap_arap_bin2_unif <- cutia_tap_arap_bin2 |> 
  ajustar_modelos_Distance(
    funcao_chave = "unif",
    termos_ajuste = "cos",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 5892.194
Fitting uniform key function with cosine(1) adjustments
AIC= 5692.195
Fitting uniform key function with cosine(1,2) adjustments
AIC= 5683.645
Fitting uniform key function with cosine(1,2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5648.379
Fitting uniform key function with cosine(1,2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5630.214
Fitting uniform key function with cosine(1,2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5617.709
Warning: Detection function is not strictly monotonic!

Terceira binagem


cutia_tap_arap_bin3_unif <- cutia_tap_arap_bin3 |> 
  ajustar_modelos_Distance(
    funcao_chave = "unif",
    termos_ajuste = "cos",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 4285.889
Fitting uniform key function with cosine(1) adjustments
AIC= 4053.818
Fitting uniform key function with cosine(1,2) adjustments
AIC= 4054.276

Uniform key function with cosine(1) adjustments selected.
5.1.2.3.3.2 Half-Normal sem termos de ajuste e com termos de ajuste

Primeira binagem


cutia_tap_arap_bin1_hn <- cutia_tap_arap_bin1 |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Fitting half-normal key function
AIC= 5302.34
Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 5302.34
Fitting half-normal key function with cosine(2) adjustments
AIC= 5278.289
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5251.854
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5234.791
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5226.873
Fitting half-normal key function with cosine(2,3,4,5,6) adjustments
Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Half-normal key function with cosine(2,3,4,5) adjustments selected.
Warning: Detection function is not strictly monotonic!Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 5302.34
Fitting half-normal key function with Hermite(4) adjustments
AIC= 5304.025

Half-normal key function selected.

Segunda binagem


cutia_tap_arap_bin2_hn <- cutia_tap_arap_bin2 |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Fitting half-normal key function
AIC= 5701.235
Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 5701.235
Fitting half-normal key function with cosine(2) adjustments
AIC= 5667.729
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5643.501
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 7183.526

Half-normal key function with cosine(2,3) adjustments selected.
Warning: Detection function is not strictly monotonic!Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 5701.235
Fitting half-normal key function with Hermite(4) adjustments
AIC= 5703.009

Half-normal key function selected.

Terceira binagem


cutia_tap_arap_bin3_hn <- cutia_tap_arap_bin3 |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Fitting half-normal key function
AIC= 4057.575
Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 4057.575
Fitting half-normal key function with cosine(2) adjustments
AIC= 4048.794
Fitting half-normal key function with cosine(2,3) adjustments
AIC= 4027.813
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 4018.985
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 4154.212

Half-normal key function with cosine(2,3,4) adjustments selected.
Warning: Detection function is not strictly monotonic!Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 4057.575
Fitting half-normal key function with Hermite(4) adjustments
AIC= 4059.398

Half-normal key function selected.
5.1.2.3.3.3 Hazard-rate sem termos de ajuste e com termos de ajuste

Primeira binagem


cutia_tap_arap_bin1_hr <- cutia_tap_arap_bin1 |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 5248.75
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 5248.75
Fitting hazard-rate key function with cosine(2) adjustments
Warning: Detection function is not strictly monotonic!AIC= 5270.746

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 5248.75
Fitting hazard-rate key function with simple polynomial(4) adjustments
AIC= 5272.362

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).

Segunda binagem


cutia_tap_arap_bin2_hr <- cutia_tap_arap_bin2 |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 5624.367
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 5624.367
Fitting hazard-rate key function with cosine(2) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 5624.367
Fitting hazard-rate key function with simple polynomial(4) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).

Terceira binagem


cutia_tap_arap_bin3_hr <- cutia_tap_arap_bin3 |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = 15)
Columns "distbegin" and "distend" in data: performing a binned analysis...
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 4042.87
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 4042.87
Fitting hazard-rate key function with cosine(2) adjustments
AIC= 4039.502
Fitting hazard-rate key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 4026.363
Fitting hazard-rate key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 4021.608
Fitting hazard-rate key function with cosine(2,3,4,5) adjustments
Error in ddf.ds(model = dsmodel, data, meta.data = meta.data, control = control,  : 
  Number of parameters to estimate exceed number of distance bins minus 1


Error in model fitting, returning: hazard-rate key function with cosine(2,3,4) adjustments

  Error: Error in ddf.ds(model = dsmodel, data, meta.data = meta.data, control = control,  : 
  Number of parameters to estimate exceed number of distance bins minus 1


Warning: Detection function is not strictly monotonic!Columns "distbegin" and "distend" in data: performing a binned analysis...
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 4042.87
Fitting hazard-rate key function with simple polynomial(4) adjustments
AIC= 4042.589
Fitting hazard-rate key function with simple polynomial(4,6) adjustments
Warning: Parameters or bounds appear to have different scalings.
  This can cause poor performance in optimization. 
  It is important for derivative free methods like BOBYQA, UOBYQA, NEWUOA.Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 4044.558

Hazard-rate key function with simple polynomial(4) adjustments selected.
5.1.2.3.4 Comparando os modelos
5.1.2.3.4.1 Tabela com o resumo comparativo dos modelos
fluxo3.1_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(
  cutia_tap_arap_bin1_unif,
  cutia_tap_arap_bin1_hn$`Sem termo`,
  cutia_tap_arap_bin1_hn$Cosseno,
  cutia_tap_arap_bin1_hn$`Hermite polinomial`,
  cutia_tap_arap_bin1_hr$`Sem termo`,
  cutia_tap_arap_bin1_hr$Cosseno,
  cutia_tap_arap_bin1_hr$`Polinomial simples`,
  distancia_categorizada = TRUE
)

fluxo3.1_selecao_funcao_deteccao_termo_ajuste
NA
fluxo3.2_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(
  cutia_tap_arap_bin2_unif,
  cutia_tap_arap_bin2_hn$`Sem termo`,
  cutia_tap_arap_bin2_hn$Cosseno,
  cutia_tap_arap_bin2_hn$`Hermite polinomial`,
  cutia_tap_arap_bin2_hr$`Sem termo`,
  cutia_tap_arap_bin2_hr$Cosseno,
  cutia_tap_arap_bin2_hr$`Polinomial simples`,
  distancia_categorizada = TRUE
)

fluxo3.2_selecao_funcao_deteccao_termo_ajuste
fluxo3.3_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(
  cutia_tap_arap_bin3_unif,
  cutia_tap_arap_bin3_hn$`Sem termo`,
  cutia_tap_arap_bin3_hn$Cosseno,
  cutia_tap_arap_bin3_hn$`Hermite polinomial`,
  cutia_tap_arap_bin3_hr$`Sem termo`,
  cutia_tap_arap_bin3_hr$Cosseno,
  cutia_tap_arap_bin3_hr$`Polinomial simples`,
  distancia_categorizada = TRUE
)

fluxo3.3_selecao_funcao_deteccao_termo_ajuste
5.1.2.3.4.2 Gråficos de ajuste das funçÔes de detecção às probabilidades de detecção

Primeira binagem

# plotar a probabilidade de detecção observada (barras) e a esperada (linhas e pontos)
plotar_funcao_deteccao_modelos_selecionados(
  fluxo3.1_modelos_selecionados
)
$`Half-normal with cosine adjustment terms of order 2,3,4,5`
NULL

$`Uniform with cosine adjustment terms of order 1,2,3,4`
NULL

$`Hazard-rate`
NULL

$`Half-normal`
NULL

Segunda binagem

# plotar a probabilidade de detecção observada (barras) e a esperada (linhas e pontos)
plotar_funcao_deteccao_modelos_selecionados(fluxo3.2_modelos_selecionados)
$`Uniform with cosine adjustment terms of order 1,2,3,4,5`
NULL

$`Hazard-rate`
NULL

$`Half-normal with cosine adjustment terms of order 2,3`
NULL

$`Half-normal`
NULL

Terceira binagem

# Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
fluxo3.3_modelos_selecionados <- gerar_lista_modelos_selecionados(
  cutia_tap_arap_bin3_hn$`Cosseno`,
  cutia_tap_arap_bin3_hr$Cosseno,
  cutia_tap_arap_bin3_hr$`Polinomial simples`,
  cutia_tap_arap_bin3_hr$`Sem termo`,
  cutia_tap_arap_bin3_unif,
  cutia_tap_arap_bin3_hn$`Sem termo`, 
  nome_modelos_selecionados = fluxo3.3_selecao_funcao_deteccao_termo_ajuste
)

# plotar a probabilidade de detecção observada (barras) e a esperada (linhas e pontos)
plotar_funcao_deteccao_modelos_selecionados(fluxo3.3_modelos_selecionados)

$`Half-normal with cosine adjustment terms of order 2,3,4`
NULL

$`Hazard-rate with cosine adjustment terms of order 2,3,4`
NULL

$`Hazard-rate with simple polynomial adjustment term of order 4`
NULL

$`Hazard-rate`
NULL

$`Uniform with cosine adjustment term of order 1`
NULL

$`Half-normal`
NULL

5.1.2.3.4.3 Teste de bondade de ajuste dos modelos e Q-Q plots

Primeira binagem

bondade_ajuste_fluxo3.1 <- testar_bondade_ajuste(fluxo3.1_modelos_selecionados,
  plot = TRUE,
  chisq = TRUE, 
  intervalos_distancia =  seq(
    from = 0,
    to  = 15,
    by = 1.5
  )
)

bondade_ajuste_fluxo3.1

Segunda binagem

bondade_ajuste_fluxo3.2 <- testar_bondade_ajuste(fluxo3.2_modelos_selecionados,
  plot = TRUE,
  chisq = TRUE, 
  intervalos_distancia =  
    c(0, seq(1, 15, 1.4))
  )


bondade_ajuste_fluxo3.2
$`Uniform with cosine adjustment terms of order 1,2,3,4,5`

Goodness of fit results for ddf object

Chi-square tests

P = 0 with 5 degrees of freedom

$`Hazard-rate`

Goodness of fit results for ddf object

Chi-square tests

P = 0 with 8 degrees of freedom

$`Half-normal with cosine adjustment terms of order 2,3`

Goodness of fit results for ddf object

Chi-square tests

P = 0 with 7 degrees of freedom

$`Half-normal`

Goodness of fit results for ddf object

Chi-square tests

P = 0 with 9 degrees of freedom

Terceira binagem

bondade_ajuste_fluxo3.3 <- testar_bondade_ajuste(fluxo3.3_modelos_selecionados,
  plot = TRUE,
  chisq = TRUE, 
  intervalos_distancia =  seq(
    from = 0,
    to  = 15,
    by = 2.5
  )
)

bondade_ajuste_fluxo3.3
$`Half-normal with cosine adjustment terms of order 2,3,4`

Goodness of fit results for ddf object

Chi-square tests

P = 4.1621e-08 with 1 degrees of freedom

$`Hazard-rate with cosine adjustment terms of order 2,3,4`

Goodness of fit results for ddf object

Chi-square tests

No degrees of freedom for test

$`Hazard-rate with simple polynomial adjustment term of order 4`

Goodness of fit results for ddf object

Chi-square tests

P = 1.7697e-13 with 2 degrees of freedom

$`Hazard-rate`

Goodness of fit results for ddf object

Chi-square tests

P = 1.7675e-13 with 3 degrees of freedom

$`Uniform with cosine adjustment term of order 1`

Goodness of fit results for ddf object

Chi-square tests

P = 1.521e-14 with 4 degrees of freedom

$`Half-normal`

Goodness of fit results for ddf object

Chi-square tests

P = 3.4417e-15 with 4 degrees of freedom
5.1.2.3.5 Avaliando as estimativas de AbundĂąncia e Densidade
5.1.2.3.5.1 CaracterĂ­sticas da ĂĄrea de estudo e da taxa de encontro

Primeira binagem

# gerar resultados sobre a ĂĄrea, nĂșmero de detecçÔes, e taxa de encontro  
fluxo3.1_caracteristicas_area_estudo_taxa_encontro <- fluxo3.1_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.1_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "area_estudo"
  )

fluxo3.1_caracteristicas_area_estudo_taxa_encontro

Segunda binagem

# gerar resultados sobre a ĂĄrea, nĂșmero de detecçÔes, e taxa de encontro  
fluxo3.2_caracteristicas_area_estudo_taxa_encontro <- fluxo3.2_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.2_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "area_estudo"
  )

fluxo3.2_caracteristicas_area_estudo_taxa_encontro

Terceira binagem

# gerar resultados sobre a ĂĄrea, nĂșmero de detecçÔes, e taxa de encontro  
fluxo3.3_caracteristicas_area_estudo_taxa_encontro <- fluxo3.3_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.3_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "area_estudo"
  )

fluxo3.3_caracteristicas_area_estudo_taxa_encontro
5.1.2.3.5.2 Características de abundùncia, esforço e detecção

Primeira binagem

# gerar resultados sobre a abundĂąncia
fluxo3.1_caracteristicas_abundancia <- fluxo3.1_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.1_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "abundancia"
  )

fluxo3.1_caracteristicas_abundancia

Segunda binagem

# gerar resultados sobre a abundĂąncia
fluxo3.2_caracteristicas_abundancia <- fluxo3.2_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.2_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "abundancia"
  )

fluxo3.2_caracteristicas_abundancia

Terceira binagem

# gerar resultados sobre a abundĂąncia
fluxo3.3_caracteristicas_abundancia <- fluxo3.3_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.3_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "abundancia"
  )

fluxo3.3_caracteristicas_abundancia
5.1.2.3.5.3 CaracterĂ­sticas de densidade

Primeira binagem

# gerar resultados sobre a densidade
fluxo3.1_caracteristicas_densidade <- fluxo3.1_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.1_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "densidade"
  )

fluxo3.1_caracteristicas_densidade

Segunda binagem

# gerar resultados sobre a densidade
fluxo3.2_caracteristicas_densidade <- fluxo3.2_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.2_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "densidade"
  )

fluxo3.2_caracteristicas_densidade

Terceira binagem

# gerar resultados sobre a densidade
fluxo3.3_caracteristicas_densidade <- fluxo3.3_modelos_selecionados |> 
  gerar_resultados_Distance(
    resultado_selecao_modelos = fluxo3.3_selecao_funcao_deteccao_termo_ajuste,
    tipo_de_resultado = "densidade"
  )

fluxo3.3_caracteristicas_densidade

5.1.3 Fluxo 4 - Amostragem por DistĂąncia com MĂșltiplas CovariĂĄveis

Aqui vamos usar a abordagem do Fluxo 2, sem amostragens repetidas, para o ajuste de covariåveis. Vamos usar o tamanho do grupo (size) e tempo de denso percorrido até cada observação como exemplo de covariåveis.

5.1.3.1 Carregando os dados

Aqui vamos trabalhar com os dados filtrados, sem repetiçÔes. O nĂșmero de observaçÔes total foi de 55.

5.1.3.2 Plotando o histograma

cutias_cov_distance |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?Warning: Removed 2 rows containing missing values (`stat_boxplot()`).Warning: Removed 2 rows containing non-finite values (`stat_bin()`).

5.1.3.3 Ajustando diferentes modelos com covariĂĄveis

Para o uso de coveriåveis, podemos usar somente as distribuiçÔes half-normal ou hazard-rate, pois ambas possuem o parùmetro escalar (sigma) pelo qual o vetor das covariåveis serå multiplicado. Não é recomendåvel o uso de termos de ajuste com o uso de covariåveis pela grande chance de perda de monotonicidade nas curvas das funçÔes de detecção. Assim, vamos trabalhar com as seguintes combinaçÔes de modelos.

5.1.3.3.1 Half-normal sem termos de ajuste (HN)
# ajustando a função de detecção half-normal, sem covariåvel, para um truncamento de 10% dos dados
cutias_cov_distance_hn <- cutias_cov_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = "10%"
    )
Fitting half-normal key function
AIC= 271.27
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 271.27
Fitting half-normal key function with cosine(2) adjustments
AIC= 273.177

Half-normal key function selected.
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 271.27
Fitting half-normal key function with Hermite(4) adjustments
AIC= 273.247

Half-normal key function selected.
cutias_cov_distance_hn$`Sem termo`

Distance sampling analysis object

Detection function:
 Half-normal key function 

Estimated abundance in covered region: 60.37826 
5.1.3.3.2 HN + Tamanho do grupo (HN + S)
# ajustando a função de detecção half-normal, com tamanho do grupo como covariåvel, para um truncamento de 10% dos dados
cutias_cov_distance_hn_size <- cutias_cov_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = "10%",
    formula = ~ size
    )
Fitting half-normal key function
AIC= 271.57
cutias_cov_distance_hn_size

Distance sampling analysis object

Detection function:
 Half-normal key function 

Estimated abundance in covered region: 65.04594 
5.1.3.3.3 HN + Tamanho do grupo (HN + S)
# ajustando a função de detecção half-normal, com tamanho do grupo como covariåvel, para um truncamento de 10% dos dados
cutias_cov_distance_hn_size_time <- cutias_cov_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = "10%",
    formula = ~ size + cense_time
    )
Fitting half-normal key function
AIC= 270.876
cutias_cov_distance_hn_size_time

Distance sampling analysis object

Detection function:
 Half-normal key function 

Estimated abundance in covered region: 66.59063 
5.1.3.3.4 Hazard-rate sem termos de ajuste (HZ)

cutias_cov_distance_hr <- cutias_cov_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = "10%"
    )
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 273.379
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 273.379
Fitting hazard-rate key function with cosine(2) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 276.134

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 273.379
Fitting hazard-rate key function with simple polynomial(4) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 277.333

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).
cutias_cov_distance_hr$`Sem termo`

Distance sampling analysis object

Detection function:
 Hazard-rate key function 

Estimated abundance in covered region: 61.45591 
5.1.3.3.4.1 HZ + Tamanho do grupo (HZ + S)
# ajustando a função de detecção hazard-rate, com tamanho do grupo como covariåvel, para um truncamento de 10% dos dados
cutias_cov_distance_hr_size <- cutias_cov_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = "10%",
    formula = ~ size
    )
Fitting hazard-rate key function
AIC= 272.886
cutias_cov_distance_hr_size

Distance sampling analysis object

Detection function:
 Hazard-rate key function 

Estimated abundance in covered region: 59.06912 
5.1.3.3.4.2 HZ + Tamanho do grupo (HZ + S)
# ajustando a função de detecção hazard-rate, com tamanho do grupo como covariåvel, para um truncamento de 10% dos dados
cutias_cov_distance_hr_size_time <- cutias_cov_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = "10%",
    formula = ~ size + cense_time
    )
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 268.906
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).
cutias_cov_distance_hr_size_time

Distance sampling analysis object

Detection function:
 Hazard-rate key function 

Estimated abundance in covered region: 1099.396 
5.1.3.3.5 Comparando os modelos
5.1.3.3.5.1 Tabela com o resumo comparativo dos modelos

Aqui, vamos selecionar somente os modelos sem termos de ajuste, com e sem covariĂĄveis.

cutias_cov_distance_melhor_modelo <- 
  selecionar_funcao_deteccao_termo_ajuste(
  cutias_cov_distance_hn$`Sem termo`,
  cutias_cov_distance_hn_size,
  cutias_cov_distance_hn_size_time,
  cutias_cov_distance_hr$`Sem termo`,
  cutias_cov_distance_hr_size,
  cutias_cov_distance_hr_size_time
)

cutias_cov_distance_melhor_modelo
NA

Observe que nesse caso as covariĂĄvies alteraram pouco o ajuste dos modelos.

5.1.3.3.5.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção

Ainda estamos ajustando a função para poder gerar os gråficos dos modelos com covariåveis. A função criada para os gråficos ainda não comporta os dados de modelos com covariåveis.

modelos_cutias_cov_distance <-
  gerar_lista_modelos_selecionados(
    cutias_cov_distance_hr_size_time,
    cutias_cov_distance_hn_size_time,
    cutias_cov_distance_hn$`Sem termo`,
    cutias_cov_distance_hn_size,
    cutias_cov_distance_hr_size,
    cutias_cov_distance_hr$`Sem termo`,
    nome_modelos_selecionados = cutias_cov_distance_melhor_modelo
  )

plotar_funcao_deteccao_modelos_selecionados(modelos_cutias_cov_distance)

$`Hazard-rate`
NULL

$`Half-normal`
NULL

$`Half-normal`
NULL

$`Half-normal`
NULL

$`Hazard-rate`
NULL

$`Hazard-rate`
NULL

5.1.3.3.5.3 Teste de bondade de ajuste dos modelos e Q-Q plots

Ainda estamos ajustando a função para poder gerar a tabela com os resultados do Cramér-von Mises e os gråficos dos modelos com covariåveis. A função criada para gerar tabela e os Q-Q plots ainda não comporta os dados de modelos com covariåveis.

testar_bondade_ajuste(
  modelos_cutias_cov_distance,
  plot = TRUE,
  nboot = 100
)

NA

5.1.3.3.6 Avaliando as estimativas de AbundĂąncia e Densidade

Para o uso de covariåveis, as estimativas de abundùncia/densidade devem ser feitas através do bootstrap (função bootdht do Distance). Ainda estamos implementando o bootstrap em nosso fluxo de estimativas de taxa de encontro, abundùncia e densidade.

5.1.3.3.6.1 Área coberta pela Amostragem

gerar_resultados_Distance(
  modelos_cutias_cov_distance,
  cutias_cov_distance_melhor_modelo,
  tipo_de_resultado = "area_estudo"
  )
NA
5.1.3.3.6.2 Ábundùncia

gerar_resultados_Distance(
  modelos_cutias_cov_distance,
  cutias_cov_distance_melhor_modelo,
  tipo_de_resultado = "abundancia"
  )
NA
5.1.3.3.6.3 Densidade

gerar_resultados_Distance(
  modelos_cutias_cov_distance,
  cutias_cov_distance_melhor_modelo,
  tipo_de_resultado = "densidade"
  )
NA

5.1.4 Fluxo 5 - Amostragem por distùncia com estratificação por Unidade de Conservação

A estratificação dos dados a partir do pacote Distance para o R só é possível através da variåvel Region.Label. Assim, apresentamos um fluxo de estratificação utilizando ainda os dados da cutia, Dasyprocta croconota, para mais de uma unidade de conservação.

5.1.4.1 Explorando os dados dentro de cada estrato espacial:

Na PARTE IV - Explorando e selecionando os dados para as anĂĄlises, filtramos os dados de Dasyprocta croconota. A espĂ©cie foi observada em quatro Unidades de Conservação, com os respectivos nĂșmeros de ocorrĂȘncia: Resex TapajĂłs-Arapiuns (n = 1395), Parna da Serra do Pardo (n = 257), Esec da Terra do Meio (n = 235), e Resex Riozinho do AnfrĂ­sio (n = 225). Em todas as UCs o nĂșmero de observaçÔes Ă© alto, de modo que incluĂ­mos todas as UCs na anĂĄlise de dados.

5.1.5 Carregar Dados

# filtrar dados das cutias para as quatro UCS onde ocorre:
cutias <- filtrar_dados(
  nome_ucs = c(
    "resex_tapajos_arapiuns", 
    "parna_da_serra_do_pardo",
    "esec_da_terra_do_meio", 
    "resex_riozinho_do_anfrisio"
  ),
  nome_sps = "dasyprocta_croconota",
  validacao_obs = "especie"
)

cutias_distance <- transformar_dados_formato_Distance(
  cutias,
  amostras_repetidas = TRUE)

cutias_distance
NA
NA
5.1.5.0.1 Plotando o histograma das frequĂȘncias de ocorrĂȘncia pela distĂąncia
5.1.5.0.1.1 Dados Globais

Plotando o histograma para os dados globais.

cutias_distance |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
5.1.5.0.1.2 Por Estrato

Plotando o histograma para cada uma das UCS

5.1.5.0.1.2.1 Resex TapajĂłs-Arapiuns

cutias_tap_distance <- filtrar_dados(
  nome_ucs = "resex_tapajos_arapiuns",
  nome_sps = "dasyprocta_croconota",
  validacao_obs = "especie"
) |> 
  transformar_dados_formato_Distance(amostras_repetidas = TRUE)

cutias_tap_distance |> 
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.5.0.1.2.2 Parna Serra do Pardo

cutias_par_distance <- filtrar_dados(
  nome_ucs = "parna_da_serra_do_pardo",
  nome_sps = "dasyprocta_croconota",
  validacao_obs = "especie"
)|> 
  transformar_dados_formato_Distance(amostras_repetidas = TRUE)

cutias_par_distance |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.5.0.1.2.3 Esec da Terra do Meio

cutias_ter_distance <- filtrar_dados(
  nome_ucs = "esec_da_terra_do_meio",
  nome_sps = "dasyprocta_croconota",
  validacao_obs = "especie"
) |> 
  transformar_dados_formato_Distance(amostras_repetidas = TRUE)

cutias_ter_distance |> 
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.5.0.1.2.4 Resex Riozinho do AnfrĂ­sio

cutias_anf_distance <- filtrar_dados(
  nome_ucs = "resex_riozinho_do_anfrisio",
  nome_sps = "dasyprocta_croconota",
  validacao_obs = "especie"
) |> 
  transformar_dados_formato_Distance(amostras_repetidas = TRUE)

cutias_anf_distance |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
5.1.5.0.2 Ajustando diferentes modelos para dados Globais

Para ajustar os modelos aos dados globais e estratificados, mantivemos a mesma distùncia de truncamento para os dados das cutias na Resex Tapajós-Arapiuns, de 10%, uma vez que a distrbuição dos dados é semelhante tanto nos dados globais como nas UCs analisadas.

5.1.5.0.2.1 Uniforme com termos de ajuste Cosseno e polinomial simples
# ajustando a função de detecção uniforme para um truncamento de 10% dos dados
cutias_distance_unif <- cutias_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "unif",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 10138.94
Fitting uniform key function with cosine(1) adjustments
AIC= 9859.72
Fitting uniform key function with cosine(1,2) adjustments
AIC= 9856.899
Fitting uniform key function with cosine(1,2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9789.559
Fitting uniform key function with cosine(1,2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9756.641
Fitting uniform key function with cosine(1,2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9735.379
Warning: Detection function is not strictly monotonic!Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 10138.94
Fitting uniform key function with simple polynomial(2) adjustments
AIC= 9918.804
Fitting uniform key function with simple polynomial(2,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9861.06
Fitting uniform key function with simple polynomial(2,4,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9862.176

Uniform key function with simple polynomial(2,4) adjustments selected.
Warning: Detection function is not strictly monotonic!
5.1.5.0.2.2 Half-Normal sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_distance_hn <- cutias_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = "10%")
Fitting half-normal key function
AIC= 9878.263
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 9878.263
Fitting half-normal key function with cosine(2) adjustments
AIC= 9845.472
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9789.663
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9758.006
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9722.9
Fitting half-normal key function with cosine(2,3,4,5,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 9648.391
Warning: Detection function is not strictly monotonic!Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 9878.263
Fitting half-normal key function with Hermite(4) adjustments
AIC= 9879.673

Half-normal key function selected.
5.1.5.0.2.3 Hazard-rate sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção hazard-rate para um truncamento de 10% dos dados
cutias_distance_hr <- cutias_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = "10%")
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 9427.867
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 9427.867
Fitting hazard-rate key function with cosine(2) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 9427.867
Fitting hazard-rate key function with simple polynomial(4) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).
5.1.5.0.3 Comparando os modelos
5.1.5.0.3.1 Tabela com o resumo comparativo dos modelos
melhor_modelo_cutias <- selecionar_funcao_deteccao_termo_ajuste(
  cutias_distance_unif$Cosseno,
  cutias_distance_unif$`Polinomial simples`,
  cutias_distance_hn$`Sem termo`,
  cutias_distance_hn$Cosseno,
  cutias_distance_hn$`Hermite polinomial`,
  cutias_distance_hr$`Sem termo`,
  cutias_distance_hr$Cosseno,
  cutias_distance_hr$`Polinomial simples`
)

melhor_modelo_cutias
5.1.5.0.3.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
modelos_cutias <- gerar_lista_modelos_selecionados(
  cutias_distance_hr$`Sem termo`,
  cutias_distance_hn$Cosseno,
  cutias_distance_unif$Cosseno,
  cutias_distance_unif$`Polinomial simples`,
  cutias_distance_hn$`Sem termo`,
  nome_modelos_selecionados = melhor_modelo_cutias
)

plotar_funcao_deteccao_modelos_selecionados(modelos_cutias)

$`Hazard-rate`
NULL

$`Half-normal with cosine adjustment terms of order 2,3,4,5,6`
NULL

$`Uniform with cosine adjustment terms of order 1,2,3,4,5`
NULL

$`Uniform with simple polynomial adjustment terms of order 2,4`
NULL

$`Half-normal`
NULL

5.1.5.0.3.3 Teste de bondade de ajuste dos modelos e Q-Q plots
#criar uma lista com os modelos selecionados, na ordem de seleção
testar_bondade_ajuste(
  modelos_cutias,
  plot = TRUE,
  chisq = FALSE,
)

NA

Aqui são gerados Q-Q plots que permitem avaliar a qualidade do ajuste dos modelos. E também uma tabela com os resultados do Carmér-von Mises, onde W é o valor do teste e p seu valor de significùncia. Nesse caso, quanto maior o valor de p, melhor o ajuste do modelo.

5.1.5.0.4 Avaliando as estimativas de AbundĂąncia e Densidade

Aqui, sĂŁo resumidos os dados de taxa de encontro, abundĂąncia e densidade em trĂȘs tabelas.

5.1.5.0.4.1 Área coberta pela Amostragem
gerar_resultados_Distance(
  dados = modelos_cutias,
  resultado_selecao_modelos = melhor_modelo_cutias,
  tipo_de_resultado = "area_estudo", 
  estratificacao = TRUE
)
5.1.5.0.4.2 Ábundùncia

gerar_resultados_Distance(
  dados = modelos_cutias,
  resultado_selecao_modelos = melhor_modelo_cutias,
  tipo_de_resultado = "abundancia", 
  estratificacao = TRUE
)
NA
5.1.5.0.4.3 Densidade

gerar_resultados_Distance(
  dados = modelos_cutias,
  resultado_selecao_modelos = melhor_modelo_cutias,
  tipo_de_resultado = "densidade", 
  estratificacao = TRUE
)
NA
5.1.5.0.5 Ajustando modelos para cada estrato espacial (Unidade de Conservação)

A redução no tamanho amostral geralmente faz com que os modelos para os dados globais tenham um ajuste melhor que os modelos ajustados aos estratos. Entretanto, para os dados do Monitora, considerando alguns ruĂ­dos amostrais sobre a distribuição dos dados, o excesso de repetiçÔes, resultados melhores de ajuste tĂȘm sido obtidos para conjutnos de dados menores.

Nas anålises anteriores, os parùmetros de ajuste dos modelos e valores de AIC foram gerados somente para os dados globais. Porém, as estimativas relacionadas a årea de estudo, abundùncia e densidade, foram geradas para cada estrato.

Um critério para avaliar se o ajuste das funçÔes para os dados estratificados foi melhor que para os dados globais é a comparação do somatório dos valores de AIC para cada estrato com o valor de AIC do modelo global. Se a soma dos valores de AIC dos estratos for menor que o AIC global, significa que o ajuste foi melhor para os dados estratificados.

Assim, escolhemos um dos modelos testados anteriormente para os dados globais, que foi o Half-normal. Escolhemos o segundo melhor modelo porque consideramos que o ajuste do Hazard-rate, apesar de apresentar os melhores valores de AIC e teste de ajuste de bondade, foi sensível ao pico de observaçÔes próximo a zero, substimando as estimativas de probabilidade de detecção. Assim, vamos comparar o AIC global para o modelo do tipo Half-normal com os AICs das funçÔes ajustadas para os dados de cada Unidade de Conservação.

5.1.5.0.5.1 Half-Normal

5.1.5.0.5.1.1 Dados Globais

5.1.5.0.5.1.2 Resex TapajĂłs-Arapiuns

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_tap_distance_hn <- cutias_tap_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 6375.771
Fitting half-normal key function with cosine(2) adjustments
AIC= 6349.7
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6321.849
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6293.72
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6282.536
Fitting half-normal key function with cosine(2,3,4,5,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6220.851
Warning: Detection function is not strictly monotonic!

5.1.5.0.5.1.3 Resex TapajĂłs-Arapiuns

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_tap_distance_hn <- cutias_tap_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 6375.771
Fitting half-normal key function with cosine(2) adjustments
AIC= 6349.7
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6321.849
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6293.72
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6282.534
Fitting half-normal key function with cosine(2,3,4,5,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 6587.824

Half-normal key function with cosine(2,3,4,5) adjustments selected.
Warning: Detection function is not strictly monotonic!

5.1.5.0.5.1.4 Parna Serra do Pardo

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_par_distance_hn <- cutias_par_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 1150.254
Fitting half-normal key function with cosine(2) adjustments
AIC= 1143.402
Fitting half-normal key function with cosine(2,3) adjustments
AIC= 1152.485

Half-normal key function with cosine(2) adjustments selected.

5.1.5.0.5.1.5 Esec da Terra do Meio

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados

cutias_ter_distance_hn <- cutias_ter_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 1056.95
Fitting half-normal key function with cosine(2) adjustments
AIC= 1056.994

Half-normal key function selected.

5.1.5.0.5.1.6 Resex Riozinho do AnfrĂ­sio

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_anf_distance_hn <- cutias_anf_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 1051.012
Fitting half-normal key function with cosine(2) adjustments
AIC= 1047.578
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not strictly monotonic!AIC= 1039.252
Fitting half-normal key function with cosine(2,3,4) adjustments
AIC= 1056.923

Half-normal key function with cosine(2,3) adjustments selected.
Warning: Detection function is not strictly monotonic!
5.1.5.0.6 Comparando os modelos
5.1.5.0.6.1 Tabela com o resumo comparativo dos modelos
modelo_cutias_estrat
$tabela_aics

$comparacao_aics
$comparacao_aics$AIC_global
[1] 9648.391

$comparacao_aics$AIC_locais
[1] 9522.139
5.1.5.0.6.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
modelos_cutias_estrat <- gerar_lista_modelos_selecionados(
  cutias_distance_hn$Cosseno,
  cutias_tap_distance_hn,
  cutias_par_distance_hn,
  cutias_ter_distance_hn,
  cutias_anf_distance_hn,
  nome_modelos_selecionados = modelo_cutias_estrat
)

plotar_funcao_deteccao_modelos_selecionados(modelos_cutias_estrat)

5.1.6 Fluxo 6 - Amostragem por distĂąncia estratificada por ano

Para obter as estimativas anuais de densidade continuaremos utilizando a abordagem do Fluxo 2, com amostragens sem repetição.

5.1.6.1 Carregando os dados

Aqui vamos trabalhar com os dados filtrados, sem repetiçÔes. O nĂșmero de observaçÔes total foi de 55.

cutias_year <- filtrar_dados(
  nome_ucs = "resex_tapajos_arapiuns", 
  nome_sps = "dasyprocta_croconota",
  validacao_obs = "especie"
)

cutias_year_distance <- transformar_dados_formato_Distance(
  cutias_year,
  amostras_repetidas = FALSE)

cutias_year_distance
5.1.6.1.1 Plotando o histograma das frequĂȘncias de ocorrĂȘncia pela distĂąncia
5.1.6.1.1.1 Dados Globais

Plotando o histograma para os dados globais.

cutias_year_distance |> 
  tidyr::drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
5.1.6.1.1.2 Por Estrato

Plotando o histograma para cada ano.

5.1.6.1.1.2.1 2014

cutia_2014 <- cutias_year_distance |> 
  dplyr::filter(year == 2014)

cutia_2014 |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.6.1.1.2.2 **2015*

cutia_2015 <- cutias_year_distance |> 
  dplyr::filter(year == 2015)

cutia_2015 |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.6.1.1.2.3 2016

cutia_2016 <- cutias_year_distance |> 
  dplyr::filter(year == 2016)

cutia_2016 |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.6.1.1.2.4 2017

cutia_2017 <- cutias_year_distance |> 
  dplyr::filter(year == 2017)

cutia_2017 |> 
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.6.1.1.2.5 2018

cutia_2018 <- cutias_year_distance |> 
  dplyr::filter(year == 2018)

cutia_2018 |> 
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.6.1.1.2.6 2019

cutia_2019 <- cutias_year_distance |> 
  dplyr::filter(year == 2019)

cutia_2019 |> 
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.6.1.1.2.7 2020

cutia_2020 <- cutias_year_distance |> 
  dplyr::filter(year == 2020)

cutia_2020|> 
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?

5.1.6.1.1.2.8 2021

cutia_2021 <- cutias_year_distance |> 
  dplyr::filter(year == 2021)

cutia_2021 |> 
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo(largura_caixa = 1)
Warning: Continuous y aesthetic
â„č did you forget `aes(group = ...)`?
5.1.6.1.2 Ajustando diferentes modelos para dados Globais

Para ajustar os modelos aos dados globais e estratificados, mantivemos a mesma distùncia de truncamento para os dados das cutias na Resex Tapajós-Arapiuns, de 10%, uma vez que a distrbuição dos dados é semelhante tanto nos dados globais como nas UCs analisadas.

5.1.6.1.2.1 Uniforme com termos de ajuste Cosseno e polinomial simples
# ajustando a função de detecção uniforme para um truncamento de 10% dos dados
cutias_distance_unif_year <- cutias_year_distance |>
  dplyr::filter(year != 2014) |> 
  dplyr::mutate(Region.Label = year) |> 
  ajustar_modelos_Distance(
    funcao_chave = "unif",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 2599.728
Fitting uniform key function with cosine(1) adjustments
AIC= 2514.283
Fitting uniform key function with cosine(1,2) adjustments
AIC= 2515.63

Uniform key function with cosine(1) adjustments selected.
Starting AIC adjustment term selection.
Fitting uniform key function
AIC= 2599.728
Fitting uniform key function with simple polynomial(2) adjustments
AIC= 2536.817
Fitting uniform key function with simple polynomial(2,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 2515.387
Fitting uniform key function with simple polynomial(2,4,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 2517.218

Uniform key function with simple polynomial(2,4) adjustments selected.
Warning: Detection function is not strictly monotonic!
5.1.6.1.2.2 Half-Normal sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_distance_hn_year <- cutias_year_distance |> 
  dplyr::filter(year != 2014) |> 
  dplyr::mutate(Region.Label = year) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    truncamento = "10%")
Fitting half-normal key function
AIC= 2521.42
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 2521.42
Fitting half-normal key function with cosine(2) adjustments
AIC= 2518.639
Fitting half-normal key function with cosine(2,3) adjustments
AIC= 2514.532
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 2508.791
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 2581.978

Half-normal key function with cosine(2,3,4) adjustments selected.
Warning: Detection function is not strictly monotonic!Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 2521.42
Fitting half-normal key function with Hermite(4) adjustments
AIC= 2523.242

Half-normal key function selected.
5.1.6.1.2.3 Hazard-rate sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção hazard-rate para um truncamento de 10% dos dados
cutias_distance_hr_year <- cutias_year_distance |> 
  dplyr::filter(year != 2014) |> 
  dplyr::mutate(Region.Label = year) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hr",
    truncamento = "10%")
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 2511.66
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 2511.66
Fitting hazard-rate key function with cosine(2) adjustments
AIC= 2519.573

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 2511.66
Fitting hazard-rate key function with simple polynomial(4) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).
5.1.6.1.3 Comparando os modelos
5.1.6.1.3.1 Tabela com o resumo comparativo dos modelos
melhor_modelo_cutias_year <- selecionar_funcao_deteccao_termo_ajuste(
  cutias_distance_unif_year$Cosseno,
  cutias_distance_unif_year$`Polinomial simples`,
  cutias_distance_hn_year$`Sem termo`,
  cutias_distance_hn_year$Cosseno,
  cutias_distance_hn_year$`Hermite polinomial`,
  cutias_distance_hr_year$`Sem termo`,
  cutias_distance_hr_year$Cosseno,
  cutias_distance_hr_year$`Polinomial simples`
)

melhor_modelo_cutias_year
5.1.6.1.3.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
modelos_cutias_year <- gerar_lista_modelos_selecionados(
  cutias_distance_hn_year$Cosseno,
  cutias_distance_hr_year$`Sem termo`,
  cutias_distance_unif_year$Cosseno,
  cutias_distance_unif_year$`Polinomial simples`,
  cutias_distance_hn_year$`Sem termo`,
  nome_modelos_selecionados = melhor_modelo_cutias_year
)

plotar_funcao_deteccao_modelos_selecionados(modelos_cutias_year)

$`Half-normal with cosine adjustment terms of order 2,3,4`
NULL

$`Hazard-rate`
NULL

$`Uniform with cosine adjustment term of order 1`
NULL

$`Uniform with simple polynomial adjustment terms of order 2,4`
NULL

$`Half-normal`
NULL

5.1.6.1.3.3 Teste de bondade de ajuste dos modelos e Q-Q plots
#criar uma lista com os modelos selecionados, na ordem de seleção
testar_bondade_ajuste(
  modelos_cutias_year,
  plot = TRUE,
  chisq = FALSE,
)

NA

Aqui são gerados Q-Q plots que permitem avaliar a qualidade do ajuste dos modelos. E também uma tabela com os resultados do Carmér-von Mises, onde W é o valor do teste e p seu valor de significùncia. Nesse caso, quanto maior o valor de p, melhor o ajuste do modelo.

5.1.6.1.4 Avaliando as estimativas de AbundĂąncia e Densidade

Aqui, sĂŁo resumidos os dados de taxa de encontro, abundĂąncia e densidade em trĂȘs tabelas.

5.1.6.1.4.1 Área coberta pela Amostragem
gerar_resultados_Distance(
  dados = modelos_cutias_year,
  resultado_selecao_modelos = melhor_modelo_cutias_year,
  tipo_de_resultado = "area_estudo", 
  estratificacao = TRUE
)
5.1.6.1.4.2 Ábundùncia
resultado_abundancia <- 
gerar_resultados_Distance(
  dados = modelos_cutias_year,
  resultado_selecao_modelos = melhor_modelo_cutias_year,
  tipo_de_resultado = "abundancia", 
  estratificacao = TRUE
)

resultado_abundancia
resultado_abundancia |>
  dplyr::mutate(ano = as.integer(Regiao)) |> 
  dplyr::group_by(ano) |> 
  dplyr::summarise(n = sum(`Abundancia estimada`)) |> 
  ggplot2::ggplot() +
  ggplot2::aes(
    x = ano,
    y = n
  ) + 
  ggplot2::geom_line() +
  ggplot2::theme_minimal()

5.1.6.1.4.3 Densidade
resultados_densidade <- 
gerar_resultados_Distance(
  dados = modelos_cutias_year,
  resultado_selecao_modelos = melhor_modelo_cutias_year,
  tipo_de_resultado = "densidade", 
  estratificacao = TRUE
)

resultados_densidade
resultados_densidade |>
  dplyr::filter(Rotulo != "Total") |> 
  dplyr::mutate(ano = as.integer(Rotulo)) |> 
  ggplot2::ggplot() +
  ggplot2::aes(
    x = ano,
    y = `Estimativa de densidade`
  ) + 
  ggplot2::geom_line() +
  ggplot2::facet_wrap(facets = ggplot2::vars(Modelo)) +
  ggplot2::theme_minimal()

5.1.6.1.5 Ajustando modelos para cada estrato temporal (ano)
5.1.6.1.5.1 Half-Normal

5.1.6.1.5.1.1 Dados Globais

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_distance_year_hn <- cutias_year_distance |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 2532.73
Fitting half-normal key function with cosine(2) adjustments
AIC= 2530.171
Fitting half-normal key function with cosine(2,3) adjustments
AIC= 2526.024
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 2520.496
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 2539.53

Half-normal key function with cosine(2,3,4) adjustments selected.
Warning: Detection function is not strictly monotonic!

5.1.6.1.5.1.2 2015

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_2015_distance_hn <- cutias_year_distance |> 
  dplyr::filter(year == 2015) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 259.852
Fitting half-normal key function with cosine(2) adjustments
AIC= 261.819

Half-normal key function selected.

5.1.6.1.5.1.3 2016

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_2016_distance_hn <- cutias_year_distance |> 
  dplyr::filter(year == 2016) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 481.41
Fitting half-normal key function with cosine(2) adjustments
AIC= 479.482
Fitting half-normal key function with cosine(2,3) adjustments
AIC= 481.579

Half-normal key function with cosine(2) adjustments selected.

5.1.6.1.5.1.4 2017

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_2017_distance_hn <- cutias_year_distance |> 
  dplyr::filter(year == 2017) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 415.83
Fitting half-normal key function with cosine(2) adjustments
AIC= 414.392
Fitting half-normal key function with cosine(2,3) adjustments
Warning: Detection function is not weakly monotonic!Warning: Detection function is not strictly monotonic!Warning: Detection function is greater than 1 at some distancesWarning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Half-normal key function with cosine(2) adjustments selected.

5.1.6.1.5.1.5 2018

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_2018_distance_hn <- cutias_year_distance |> 
  dplyr::filter(year == 2018) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 476.763
Fitting half-normal key function with cosine(2) adjustments
AIC= 478.525

Half-normal key function selected.

5.1.6.1.5.1.6 2019

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_2019_distance_hn <- cutias_year_distance |> 
  dplyr::filter(year == 2019) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 348.885
Fitting half-normal key function with cosine(2) adjustments
AIC= 350.714

Half-normal key function selected.

5.1.6.1.5.1.7 2020

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_2020_distance_hn <- cutias_year_distance |> 
  dplyr::filter(year == 2020) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 337.909
Fitting half-normal key function with cosine(2) adjustments
AIC= 388.614

Half-normal key function selected.

5.1.6.1.5.1.8 2021

# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutias_2021_distance_hn <- cutias_year_distance |> 
  dplyr::filter(year == 2021) |> 
  ajustar_modelos_Distance(
    funcao_chave = "hn",
    termos_ajuste = "cos",
    truncamento = "10%")
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 236.225
Fitting half-normal key function with cosine(2) adjustments
AIC= 237.809

Half-normal key function selected.
5.1.6.1.6 Comparando os modelos
5.1.6.1.6.1 Tabela com o resumo comparativo dos modelos
modelo_cutias_estrat_year
$tabela_aics

$comparacao_aics
$comparacao_aics$AIC_global
[1] 2520.496

$comparacao_aics$AIC_locais
[1] 2553.508
5.1.6.1.6.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
modelos_cutias_estrat <- gerar_lista_modelos_selecionados(
  cutias_distance_year_hn,
  cutias_2015_distance_hn,
  cutias_2016_distance_hn,
  cutias_2017_distance_hn,
  cutias_2018_distance_hn,
  cutias_2019_distance_hn,
  cutias_2020_distance_hn,
  cutias_2021_distance_hn,
  nome_modelos_selecionados = modelo_cutias_estrat
)

plotar_funcao_deteccao_modelos_selecionados(modelos_cutias_estrat)
LS0tCnRpdGxlOiAiRmx1eG8gZGUgdHJhYmFsaG86IGRlIHByb2R1Y2FvIGRvcyBjb2RpZ29zIGRvcyBkYWRvcyBkZSBBbW9zdHJhZ2VtIHBvciBEaXN0YW5jaWEgLSBQcm9ncmFtYSBNb25pdG9yYSBJQ01CaW8vTU1BIgphdXRob3I6ICJMdWNpYW5hIEZ1c2luYXR0byBcbiBWaXRvciBCb3JnZXMtSsO6bmlvciIKZGF0ZTogQ3JpYWRvIGVtIDMxIGRlIG1hcsOnbyBkZSAyMDIzLCBhdHVhbGl6YWRvIGVtIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgZGUgJUIKICBkZSAlWScpYApvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDYKICAgIHRvY19mbG9hdDogbm8KICAgIG51bWJlcl9zZWN0aW9uOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogc2hvdwplZGl0b3Jfb3B0aW9uczoKICBtYXJrZG93bjoKICAgIHdyYXA6IDcyCi0tLQoKIyAqKlBBUlRFIEkgLS0gQ3VpZGFkb3MgYW50ZXMgZGUgY29tZcOnYXIgYSByb2RhciBvcyBjw7NkaWdvcyBubyBSKioKCiMjKipBYnJpbmRvIG8gUHJvamV0byBgTW9uaXRvcmEuUnByb2pgKiogCgpQYXJhIHF1ZSBvIGFycXVpdm8KYHR1dG9yaWFsX2ZsdXhvX2FuYWxpc2VzLlJtZGAgZnVuY2lvbmUgZGUgbWFuZWlyYQphZGVxdWFkYSBlbSBzdWEgbcOhcXVpbmEsIHZvY8OqIGRldmUgZGVzY29tcGFjdGFyIG8gYXJxdWl2bwpgcGlwZXIzRF9tb25pdG9yYV9mbG9yZXN0YWwuemlwYC4gVW1hIG5vdmEgcGFzdGEgY29tIG8gbWVzbW8gbm9tZSBzZXLDoQpjcmlhZGEgbm8gZGlyZXTDs3JpbyBlc2NvbGhpZG8gcGFyYSBleGVjdXRhciBhIGRlc2NvbXBhY3Rhw6fDo28uIE5lbGEsIHZvY8OqCmRldmVyw6EgY2xpY2FyIGR1YXMgdmV6ZXMgc29icmUgbyDDrWNvbmUgYE1vbml0b3JhLlJwcm9qYCBwYXJhIGNvbWXDp2FyIGEKZXhlY3V0YXIgb3MgYXJxdWl2b3MgY29udGlkb3Mgbm8gcHJvamV0by4gQW8gcmVhbGl6YXIgZXNzZSBwcm9jZWRpbWVudG8sCnZvY8OqIGdhcmFudGlyw6EgcXVlIHNldSBkaXJldMOzcmlvIGRlIHRyYWJhbGhvIGVzdGVqYSBjb25maWd1cmFkbyBjb21vIG8KZGlyZXTDs3JpbyBkYSBwYXN0YSBgcGlwZXIzZF9tb25pdG9yYV9mbG9yZXN0YWxgIGFzc2VndXJhbmRvIG8KZnVuY2lvbmFtZW50byBjb3JyZXRvIGRvcyBjw7NkaWdvcyBjb250aWRvcyBubyBwcm9qZXRvLgoKIyMgKipEaWNhcyBzb2JyZSBSTWFya2Rvd24qKgoKT3MgY8OzZGlnb3MgZGVzdGUgYXJxdWl2byBlc3TDo28gZGlzcG9uw612ZWlzIGVtIGNodW5rcywgcXVlIHBvZGVtIHNlcgpyb2RhZG9zIGluZGl2aWR1YWxtZW50ZS4KCkNhc28gbsOjbyBxdWVpcmEgcm9kYXIgcGFydGUgZG9zIGPDs2RpZ29zLCB2b2PDqiBwb2RlIGJsb3F1ZWFyIG9zIGNodW5rcwphdHJhdsOpcyBkbyBhcmd1bWVudG8gYGV2YWw9RkFMU0VgIG5hIGxpbmhhIGRlIGNvbWFuZG8gZG9zIGNodW5rcywKY29uZm9ybWUgZXhlbXBsbzoKCmBgYHtyLCBldmFsPUZBTFNFfQpgYGAKCkNhc28gbsOjbyBxdWVpcmEgbmVtIGluY2x1aXIgb3MgY8OzZGlnb3Mgbm8gcmVsYXTDs3JpbyByZXN1bHRhbnRlLCBuZW0Kcm9kYXIgb3MgY8OzZGlnb3MsIHZvY8OqIHBvZGUgdXNhciBvcyBhcmd1bWVudG9zIGBlY2hvPUZBTFNFYCBlCmBldmFsPUZBTFNFYCBuYSBsaW5oYSBkZSBjb21hbmRvIGRvcyBjaHVua3MsIGNvbmZvcm1lIGV4ZW1wbG86CgpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KYGBgCgpDYXNvIG7Do28gcXVlaXJhIHF1ZSBvcyByZXN1bHRhZG9zIGRlIGFsZ3VtIGPDs2RpZ28gYXBhcmXDp2FtIG5vIHJlbGF0w7NyaW8KZmluYWwsIHVzYXI6CgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CmBgYAoKQ2FzbyBxdWVpcmEgb21pdGlyIGRvIHJlbGF0w7NyaW8gbWVuc2FnZW5zIGRlIGF2aXNvcyBvdSBhZHZlcnTDqm5jaWFzLAp1c2FyOgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpgYGAKCgojIyAqKiBJbnN0YWxhbmRvIGUgY2FycmVnYW5kbyBvIHBhY290ZSBkaXN0ZW5jZU1vbml0b3JhZmxvcmVzdGFsKioKCmBgYHtyfQojIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1Yigidm50Ym9yZ2VzanIvZGlzdGFuY2VNb25pdG9yYWZsb3Jlc3RhbCIpCiMgCmxpYnJhcnkoZGlzdGFuY2VNb25pdG9yYWZsb3Jlc3RhbCkKYGBgCgoKIyMgKipDYXJyZWdhbmRvIG9zIHBhY290ZXMqKgoKYGBge3IgY29uZmlndXJhw6fDo28sIGluY2x1ZGU9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgojIGxpYnJhcnkoRGlzdGFuY2UpCiMgbGlicmFyeShkcGx5cikKIyBsaWJyYXJ5KERUKQojIGxpYnJhcnkoZm9yY2F0cykKIyBsaWJyYXJ5KGdncHVicikKIyBsaWJyYXJ5KGdncGxvdDIpCiMgbGlicmFyeShoZXJlKQojIGxpYnJhcnkobHVicmlkYXRlKQojIGxpYnJhcnkobXJkcykKIyBsaWJyYXJ5KHBsb3RseSkKIyBsaWJyYXJ5KHB1cnJyKQojIGxpYnJhcnkocmVhZHIpCiMgbGlicmFyeShyZWFkeGwpCiMgbGlicmFyeShzdHJpbmdpKQojIGxpYnJhcnkoc3RyaW5ncikKIyBsaWJyYXJ5KHRpZHlyKQojIGxpYnJhcnkodGlkeXNlbGVjdCkKIyBzb3VyY2UocGFzdGUwKGhlcmU6OmhlcmUoKSwgIi9SL21pbmhhc19mdW5jb2VzLlIiKSkKCmBgYAoKIyMgKipSc3R1ZGlvL1BhY290ZXMvdmVyc8O1ZXMvc2lzdGVtYXMgb3BlcmFjaW9uYWlzKioKCkEgdGFiZWxhIGFzZWd1aXIgw6kgdW1hIHJlZmVyw6puY2lhIHBhcmEgYXMgdmVyc8O1ZXMgZG9zIHBhY290ZXMgdXRpbGl6YWRvcwpubyBuZXNzZSBwcm9qZXRvLiBQYXJhIGdhcmFudGlyIGEgcmVwcm9kdcOnw6NvIGRvcyBjw7NkaWdvcywgw6kgaW1wb3J0YW50ZQpxdWUgbyBSIGUgb3MgcGFjb3RlcyB1c2Fkb3Mgbm8gcHJvamV0byBhcHJlc2VudGVtIGFzIGNvbmZpZ3VyYcOnw7Vlcwptw61uaW1hcyBjb250aWRhcyBuYSB0YWJlbGEgMS4KCmBgYHtyfQojICMgZ2VyYXIgaW5mb3JtYcOnw7VlcyBzb2JyZSBvcyBwYWNvdGVzIGNhcnJlZ2Fkb3MKIyBpbmZvIDwtIHNlc3Npb25JbmZvKCkKIyAKIyAjIGdlcmFyIHRhYmVsYSBjb20gb3MgcGFjb3RlcyBlIHZlcnPDtWVzCiMgdHJpYmJsZSgKIyAgIH5QYWNvdGVzLCAgICAgICAgICAgICAgICAgICAgICAgICB+VmVyc8OjbywKIyAgIHZlcnNpb24kbGFuZ3VhZ2UsICAgICAgICAgICAgICAgICB2ZXJzaW9uJHZlcnNpb24uc3RyaW5nLAojICAgaW5mbyRvdGhlclBrZ3MkZHBseXIkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJGRwbHlyJFZlcnNpb24sCiMgICBpbmZvJG90aGVyUGtncyREaXN0YW5jZSRQYWNrYWdlLCAgaW5mbyRvdGhlclBrZ3MkRGlzdGFuY2UkVmVyc2lvbiwKIyAgIGluZm8kb3RoZXJQa2dzJERUJFBhY2thZ2UsICAgICAgICBpbmZvJG90aGVyUGtncyREVCRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3MkZm9yY2F0cyRQYWNrYWdlLCAgICAgICAgaW5mbyRvdGhlclBrZ3MkZm9yY2F0cyRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3MkZmxleHRhYmxlJFBhY2thZ2UsIGluZm8kb3RoZXJQa2dzJGZsZXh0YWJsZSRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3MkZ2dwbG90MiRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkZ2dwbG90MiRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3MkZ2dwdWJyJFBhY2thZ2UsICAgICBpbmZvJG90aGVyUGtncyRnZ3B1YnIkVmVyc2lvbiwKIyAgIGluZm8kb3RoZXJQa2dzJGhlcmUkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJGhlcmUkVmVyc2lvbiwKIyAgIGluZm8kb3RoZXJQa2dzJGx1YnJpZGF0ZSRQYWNrYWdlLCBpbmZvJG90aGVyUGtncyRsdWJyaWRhdGUkVmVyc2lvbiwKIyAgIGluZm8kb3RoZXJQa2dzJG1yZHMkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJG1yZHMkVmVyc2lvbiwKIyAgIGluZm8kb3RoZXJQa2dzJHBsb3RseSRQYWNrYWdlLCAgICBpbmZvJG90aGVyUGtncyRwbG90bHkkVmVyc2lvbiwKIyAgIGluZm8kb3RoZXJQa2dzJHB1cnJyJFBhY2thZ2UsICAgICBpbmZvJG90aGVyUGtncyRwdXJyciRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3MkcmVhZHIkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJHJlYWRyJFZlcnNpb24sCiMgICBpbmZvJG90aGVyUGtncyRyZWFkeGwkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJHJlYWR4bCRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3Mkc3RyaW5naSRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3Mkc3RyaW5naSRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3Mkc3RyaW5nciRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3Mkc3RyaW5nciRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3MkdGliYmxlJFBhY2thZ2UsICAgIGluZm8kb3RoZXJQa2dzJHRpYmJsZSRWZXJzaW9uLAojICAgaW5mbyRvdGhlclBrZ3MkdGlkeXIkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJHRpZHlyJFZlcnNpb24sCiMgICBpbmZvJG90aGVyUGtncyR0aWR5c2VsZWN0JFBhY2thZ2UsaW5mbyRvdGhlclBrZ3MkdGlkeXNlbGVjdCRWZXJzaW9uCiMgKSB8PiAKIyAgIGZsZXh0YWJsZTo6cWZsZXh0YWJsZSgpIHw+IAojICAgZmxleHRhYmxlOjpzZXRfY2FwdGlvbigKIyAgICAgIlRhYmVsYSAxIC0gY29uZmlndXJhw6fDo28gZGUgcGFjb3RlcyBuZWNlc3PDoXJpb3MgZSByZXNwZWN0aXZhcyB2ZXJzw7VlcyBtw61uaW1hcyBxdWUgZGV2ZW0gc2VyIHV0aWxpemFkYXMgcGFyYSByZXByb2R1emlyIG9zIGPDs2RpZ29zIgojICAgKQpgYGAKCiMjICoqQ3VpZGFkb3MgY29tIGEgcGxhbmlsaGEgLnhsc3ggcXVlIHNlcsOhIGltcG9ydGFkYSAocGFyYSBxdWUgbWFudGVuaGEgbyBwYWRyw6NvIGRhIHBsYW5pbGhhIGRlIHJlZmVyw6puY2lhIGRvIElDTUJpbykqKgoKQSBwcmltZWlyYSBmdW7Dp8OjbyB1dGxpemFkYSwgYGNhcnJlZ2FyX2RhZG9zX2JydXRvc194bHN4KClgLCBpcsOhIGNhcnJlZ2FyCmEgcGxhbmlsaGEgZW0gZm9ybWF0byBleGNlbCwKYFBsYW5pbGhhIE9maWNpYWwgY29uc29saWRhZGEgZGUgTWFzdG8tYXZlcyAyMDE0LTIxIFZhbGlkYWRhIENFTUFWRSBDUEIgQ0VOQVAueGxzeGAsCmUgZ2VyYSBhdXRvbWF0aWNhbWVudGUgbyBhcnF1aXZvIGBkYWRvc19icnV0b3MucmRzYCBuYSBwYXN0YSBgZGF0YS1yYXdgLgpBIGZ1bsOnw6NvIHNlZ3VpbnRlIGEgc2VyIHV0aWxpemFkYSwgYGNhcnJlZ2FyX2RhZG9zX2NvbXBsZXRvcygpYCBxdWUgaXLDoQpjYXJyZWdhciBvIGFycXVpdm8gYGRhZG9zX2JydXRvcy5yZHNgLiBFc3NhIGZ1bsOnw6NvIGZvaSBlc2NyaXRhIHBhcmEKY2FycmVnYSBvcyBkYWRvcyBlIG9wZXJhciB1bWEgc8OpcmllIGRlIHRyYW5zZm9ybWHDp8O1ZXMgcGFyYSBkZXZvbHbDqi1sbyBubwpmb3JtYXRvIHBhZHJvbml6YWRvIGRvIHByb2dyYW1hICoqRElTVEFOQ0UqKiBwYXJhIFdpbmRvd3MuIFBvcnRhbnRvLApwYXJhIGdhcmFudGlyIGEgcmVwcm9kdXRpYmlsaWRhZGUgZG9zIGPDs2RpZ29zIHByb2R1emlkb3MgZW0gdmVyc8O1ZXMKYXR1YWxpemFkYXMgZGEgYmFzZSBkZSBkYWRvcyBkbyBNb25pdG9yYSwgw6kgaW1wb3J0YW50ZSB0b21hciBhbGd1bnMKY3VpZGFkb3MuCgpPIHByaW1laXJvIGUgbWFpcyBpbXBvcnRhbnRlIGN1aWRhZG8gw6kgKiptYW50ZXIgYSBjb25zaXN0w6puY2lhIGRvcyBub21lcwpkYXMgY29sdW5hcyoqIGVtIHZlcnPDtWVzIGF0dWFsaXphZGFzIGRhIGJhc2UgZGUgZGFkb3MgZG8gTW9uaXRvcmEuIEFsw6ltCmRlIGNhcnJlZ2FyIG9zIGRhZG9zLCBhIGZ1bsOnw6NvIGBjYXJyZWdhcl9kYWRvc19jb21wbGV0b3MoKWAgYXBsaWNhIHVtYQpzw6lyaWUgZGUgdHJhbnNmb3JtYcOnw7VlcyBuYXMgY29sdW5hcy4gU2V1cyBub21lcyBzw6NvIGFsdGVyYWRvcywgZSBhIGVzc2FzCnPDo28gYXRyaWJ1w61kb3MgdGlwb3MgYXByb3ByaWFkb3MgKGRhdGEsIGNhcmFjdGVyLCBmYXRvciwgaW50ZWlybyBlCm51bcOpcmljbyksIGxpbmhhcyBzw6NvIGVsaW1pbmFkYXMgZSBub3ZhcyBjb2x1bmFzIHPDo28gZ2VyZWFkYXMuIFBhcmEKZXhlbXBsaWZpY2FyLCB2ZWphIG8gY8OzZGlnbyBhYmFpeG8uIEVsZSBmb2kgZXNjcml0byBwYXJhIGV4ZWN1dGFyIGFzCnByaW1laXJhcyB0cmFuc2Zvcm1hw6fDtWVzIG5vcyBkYWRvcyBlIGNvbnN0aXR1aSBvIGNvcnBvIGRhIGZ1bsOnw6NvCmBjYXJyZWdhcl9kYWRvc19maWx0cmFkb3MoKWAuCgpgYGB7cn0KIyAjIGNhcnJlZ2FyIGEgYmFzZSBkZSBkYWRvcyBkbyBNb25pdG9yYQojIGRhZG9zX2JydXRvcyA8LSBjYXJyZWdhcl9kYWRvc19icnV0b3NfeGxzeCgpCiMgCiMgIyBnZXJhciBvIGRhdGEuZnJhbWUgZGVzZWphZG8gcmVwcm9kdXppbmRvIGFzIHRyYW5zZm9ybWHDp8O1ZXMgcmVhbGl6YWRhcyBwZWxhIGZ1bsOnw6NvIGNhcnJlZ2FyX2RhZG9zX2NvbXBsZXRvcygpCiMgZGFkb3NfZmlsdHJhZG9zIDwtIGRhZG9zX2JydXRvcyB8PiAgCiMgICAjIHNlbGVjaW9uYXIgYXMgY29sdW5hcyBuZWNlc3PDoXJpYXMgcGFyYSBhcyBhbmFsaXNlcywgcGFkcm9uaXphbmRvIG9zIG5vbWVzIHBhcmEgbyBmb3JtYXRvIERJU1RBTkNFCiMgICBkcGx5cjo6c2VsZWN0KAojICAgICB1Y19jb2RlID0gQ0RVQywKIyAgICAgdWNfbmFtZSA9IGBMb2NhbCAtIE5vbWUgZGEgVW5pZGFkZSBkZSBDb25zZXJ2YWNhb2AsCiMgICAgIGVhX251bWJlciA9IGBOdW1lcm8gZGEgRXN0YWNhbyBBbW9zdHJhbGAsCiMgICAgIGVhX25hbWUgPSBgTm9tZSBkYSBFQWAsCiMgICAgIHNlYXNvbiA9IGBFc3RhY2FvIGRvIGFub2AsCiMgICAgIHNhbXBsaW5nX2RheSA9IGBkYXRhIGRhIGFtb3N0cmFnZW1gLAojICAgICBkYXlfZWZmb3J0ID0gYEVzZm9yY28gZGUgYW1vc3RyYWdlbSB0YW1hbmhvIGRhIHRyaWxoYSAobSlgLAojICAgICBzcCA9IGBFc3BlY2llcyB2YWxpZGFkYXMgcGFyYSBhbmFsaXNlIGRvIElDTUJpb2AsCiMgICAgIGRpc3RhbmNlID0gYGRpc3RhbmNpYSAobSkgICAgIGRvIGFuaW1hbCBlbSByZWxhY2FvIGEgdHJpbGhhYCwKIyAgICAgZ3JvdXBfc2l6ZSA9IGBuIGRlIGFuaW1haXNgLAojICAgICBvYnNlcnZhZG9yZXMgPSBgbm9tZSBkb3Mgb2JzZXJ2YWRvcmVzYAojICAgKSB8PgojICAgIyBhdHJpYnVpciBvcyB0aXBvcyBjb3JyZXRvcyDDoHMgY29sdW5hcyBlIGNyaWFyIG5vdmFzIGNvbHVuYXMKIyAgICAgZHBseXI6Om11dGF0ZSgKIyAgICAgICB1Y19jYXRlZ29yeSA9IHN0cmluZ2k6OnN0cmlfZXh0cmFjdF9maXJzdF93b3JkcygKIyAgICAgICB1Y19uYW1lCiMgICAgICksCiMgICAgICMgYWJyZXZpYSBvIG5vbWUgZGFzIFVDcwojICAgICB1Y19uYW1lX2FidiA9IGZvcmNhdHM6Omx2bHNfcmV2YWx1ZSgKIyAgICAgICB1Y19uYW1lLAojICAgICAgIG5ld19sZXZlbHMgPSBjKAojICAgICAgICAgIkVUTSIsICJFTSIsICJFTiIsICJFU0dUIiwgIkZKIiwgIlBDViIsICJQQSIsICJQU0JvYyIsICJQU0JvZCIsICJQU0MiLAojICAgICAgICAgIlBTTSIsICJQU0MiLCAiUFNEIiwgIlBTUCIsICJQU08iLCAiUFBOIiwgIlBDTyIsICJQSSIsICJQSmHDuiIsICJQSnVyIiwKIyAgICAgICAgICJQTVIiLCAiUFMiLCAiUFYiLCAiUENBIiwgIlBNVCIsICJSRyIsICJSSiIsICJSVGFwIiwgIlJVIiwgIlJHIiwKIyAgICAgICAgICJSVHJvbSIsICJSQVQiLCAiUkJBIiwgIlJDSSIsICJSQ00iLCAiUlJDIiwgIlJST1AiLCAiUklBIiwgIlJSQSIsICJSVEEiCiMgICAgICAgKQojICAgICApLAojICAgICAgICMgYXRyaWJ1aXIgbyB0aXBvIGRhdGEgw6AgY29sdW5hIHNhbXBsaW5nX2RheQojICAgICAgIHllYXIgPSBsdWJyaWRhdGU6OnllYXIoCiMgICAgICAgICBzYW1wbGluZ19kYXkKIyAgICAgICApLAojICAgICAgICMgYXRyaWJ1aXIgbyB0aXBvIGZhdG9yIMOgcyBjb2x1bmFzIGRvIHRpcG8gY2FyYWN0ZXIKIyAgICAgICBhY3Jvc3MoCiMgICAgICAgICB3aGVyZSgKIyAgICAgICAgICAgaXMuY2hhcmFjdGVyCiMgICAgICAgICApLAojICAgICAgICAgYXMuZmFjdG9yCiMgICAgICAgKSwKIyAgICAgICAjIHN1YnN0aXR1aXIgc2VwYXJhZG9yZXMgZGUgbm9tZSBwb3IgIiwiCiMgICAgICAgbm92byA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKIyAgICAgICAgIG9ic2VydmFkb3JlcywgCiMgICAgICAgICAiIGUgIiwKIyAgICAgICAgICIsICIKIyAgICAgICApLAojICAgICAgICMgc3Vic3RpdHVpciBzZXBhcmFkb3JlcyBkZSBub21lIHBvciAiLCIKIyAgICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAojICAgICAgICAgbm92bywgCiMgICAgICAgICAiIEUgIiwKIyAgICAgICAgICIsICIKIyAgICAgICApLAojICAgICAgICMgc3Vic3RpdHVpciBzZXBhcmFkb3JlcyBkZSBub21lIHBvciAiLCIKIyAgICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAojICAgICAgICAgbm92bywgCiMgICAgICAgICAiLyIsCiMgICAgICAgICAiLCAiCiMgICAgICAgKSwKIyAgICAgICAjIHN1YnN0aXR1aXIgc2VwYXJhZG9yZXMgZGUgbm9tZSBwb3IgIiwiCiMgICAgICAgbm92byA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKIyAgICAgICAgIG5vdm8sIAojICAgICAgICAgIjsiLAojICAgICAgICAgIiwgIgojICAgICAgICksCiMgICAgICAgIyBzdWJzdGl0dWlyIHNlcGFyYWRvcmVzIGRlIG5vbWUgcG9yICIsIgojICAgICAgIG5vdm8gPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoCiMgICAgICAgICBub3ZvLCAKIyAgICAgICAgICIgYSAiLAojICAgICAgICAgIiwgIgojICAgICAgICkgCiMgICAgICkgfD4KIyAgICMgdHJhbnNmb3JtYXIgb3Mgbm9tZXMgZG9zIG9ic2VydmFkb3JlcyBkYSBjb2x1bmEgbm92byBlbSBjb2x1bmFzIGluZGl2aWR1YWlzCiMgdGlkeXI6OnNlcGFyYXRlX3dpZGVyX2RlbGltKAojICAgbm92bywgCiMgICAiLCIsCiMgICBuYW1lcyA9IGMoCiMgICAgICJvYnMxIiwgIm9iczIiLCAib2JzMyIsICJvYnM0IiwgIm9iczUiLCAib2JzNiIKIyAgICksCiMgICB0b29fZmV3ID0gImFsaWduX3N0YXJ0IgojICkgfD4gCiMgICAjIGdlcmFyIHVtYSBub3ZhIGNvbHVuYSBudW1iZXJfb2JzZXJ2ZXJzIGNvbSBvIG7Dum1lcm8gdG90YWwgZGUgb2JzZXJ2YWRvcmVzIGVtIHVtIG1lc21vIHRyYW5zZWN0bwojICAgZHBseXI6Om11dGF0ZSgKIyAgICAgIyBzZSBvIHZhbG9yIGRhIG9ic2VydmHDp8OjbyDDqSBkaWZlcmVudGUgZGUgTkEsIHN1YnN0aXR1aXIgcG9yIDEsIHNlIGZvciBOQSwgc3Vic3RpdHVpciBwb3IgMAojICAgICBvYnMxID0gaWZlbHNlKCFpcy5uYShvYnMxKSwgMSwgMCksCiMgICAgIG9iczIgPSBpZmVsc2UoIWlzLm5hKG9iczIpLCAxLCAwKSwKIyAgICAgb2JzMyA9IGlmZWxzZSghaXMubmEob2JzMyksIDEsIDApLAojICAgICBvYnM0ID0gaWZlbHNlKCFpcy5uYShvYnM0KSwgMSwgMCksCiMgICAgIG9iczUgPSBpZmVsc2UoIWlzLm5hKG9iczUpLCAxLCAwKSwKIyAgICAgb2JzNiA9IGlmZWxzZSghaXMubmEob2JzNiksIDEsIDApLAojICAgICAjIGdlcmEgbm92YSBjb2x1bmEgbnVtYmVyX29ic2VydmVycyBhIHBhcnRpciBkYSBzb21hIGRhcyBjb2x1bmFzIGRlIG9ic2VydmFkb3JlcyBpbmRpdmlkdWFpcwojICAgICBudW1iZXJfb2JzZXJ2ZXJzID0gb2JzMSArIG9iczIgKyBvYnMzICsgb2JzNCArIG9iczUgKyBvYnM2CiMgICApIHw+IAojICAgIyBhZ3J1cGFyIG9zIGRhZG9zIHBlbGFzIGNvbHVuYXMgZWFfbmFtZSBlIHNhbXBsaW5nX2RheQojICAgZ3JvdXBfYnkoCiMgICAgIGVhX25hbWUsIAojICAgICBzYW1wbGluZ19kYXkKIyAgICkgfD4gCiMgICAjIGFuaW5oYXIgYXMgb2JzZXJ2YcOnw7VlcyBhZ3J1cGFkYXMgdWVtIGxpc3RhcwojICAgbmVzdCgpIHw+IAojICAgIyBjb21wbGV0YXIgY29tIG8gdmFsb3IgY29ycmV0byBhcyBsaW5oYXMgdmF6aWFzIGRhcyBkYSB2YXJpw6F2ZWwgZGF5X2VmZm9ydAojICAgbXV0YXRlKAojICAgICBkYXlfZWZmb3J0MiA9IHB1cnJyOjptYXAoCiMgICAgICAgZGF0YSwgXCgueCkgcmVwKAojICAgICAgICAgLngkZGF5X2VmZm9ydFsKIyAgICAgICAgICAgIWlzLm5hKAojICAgICAgICAgICAgIC54JGRheV9lZmZvcnQKIyAgICAgICAgICAgKQojICAgICAgICAgXVsxXQojICAgICAgICkKIyAgICAgKQojICAgKSB8PiAKIyAgICMgZGVzYW5paGFyIG9zIGRhZG9zCiMgICB1bm5lc3QoCiMgICAgIGMoCiMgICAgICAgZGF0YSwgCiMgICAgICAgZGF5X2VmZm9ydDIKIyAgICAgKQojICAgKSB8PiAKIyAgICMgZGVzYWdydXBhciBvcyBkYWRvcwojICAgdW5ncm91cCgpIHw+IAojICAgIyBzZWxlY2lvbmFyIGFzIGNvbHVuYXMgZGVzZWphZGFzIGUgZXhjbHVpciBhcyBpbmRlc2VqYWRhcwojICAgc2VsZWN0KAojICAgICB0aWR5c2VsZWN0OjpzdGFydHNfd2l0aChjKCJ1YyIsICJlYSIpKSwKIyAgICAgc2Vhc29uLAojICAgICB5ZWFyLAojICAgICBzYW1wbGluZ19kYXksCiMgICAgIGRheV9lZmZvcnQgPSBkYXlfZWZmb3J0MiwKIyAgICAgc3A6bnVtYmVyX29ic2VydmVycywKIyAgICAgLWRheV9lZmZvcnQsCiMgICAgIC10aWR5c2VsZWN0OjpzdGFydHNfd2l0aCgib2JzIikKIyAgICkgfD4KIyAgICMgZmlsdHJhciBvcyBkYWRvcyBwZWxhIFVDIGUgZXNww6ljaWUgZGVzZWphZGFzCiMgICAgIGRwbHlyOjpmaWx0ZXIoCiMgICAgICAgdWNfbmFtZSA9PSAiUmVzZXggVGFwYWpvcy1BcmFwaXVucyIsCiMgICAgICAgc3AgPT0gIkRhc3lwcm9jdGEgY3JvY29ub3RhIgojICAgICApIHw+IAojICAgcmVsb2NhdGUoCiMgICAgIHVjX2NhdGVnb3J5LAojICAgICAuYmVmb3JlID0gdWNfbmFtZQojICAgKSB8PiAKIyAgIHJlbG9jYXRlKAojICAgICB1Y19uYW1lX2FidiwKIyAgICAgLmFmdGVyID0gdWNfbmFtZQojICAgKQojIAojICMgZ2VyYXIgdGFiZWxhIGRpbsOibWljYSBkb3MgZGFkb3MgY29tcGxldG9zCiMgZGFkb3NfZmlsdHJhZG9zIHw+IAojICAgc2xpY2UoCiMgICAgIDE6MTAwMAojICAgKSB8PiAKIyAgIGRhdGF0YWJsZSgKIyAgICAgZmlsdGVyID0gbGlzdCgKIyAgICAgICBwb3NpdGlvbiA9ICJ0b3AiCiMgICAgICkKIyAgICkKYGBgCgpPIHRyZWNobyBkbyBjw7NkaWdvIHF1ZSB2YWkgZGEgbGluaGEgOTYgYSAxMDYgc2VydmUgc2VsZWNpb25hciBhcGVuYXMgYXMKY29sdW5hcyBkZSBpbnRlcmVzc2UgcHJlc2VudGUgbm9zIGRhZG9zIG9yaWdpbmFpcy4gTm90ZSBxdWUgb3Mgbm9tZXMgZGFzCnBsYW5pbGhhcyBvcmlnaW5haXMgY29uc3RhbSBuZXNzZSB0cmVjaG8uIENhc28gbyBub21lIGRlIHF1YWxxdWUgdW1hCmRlc3NhcyBjb2x1bmFzIHNlamEgYWx0ZXJhZG8gYSBmdW7Dp8OjbyBkZWl4YXLDoSBkZSBmdW5jaW9uYXIuCgpPdXRybyBhc3BlY3RvIGltcG9ydGFudGUgw6kgYSBwcmVzZW7Dp2EgZGUgb2JzZXJ2YcOnw7VlcyBuw6NvIHByZWVuY2hpZGFzCihleC4gY8OpbHVsYXMgdmF6aWFzKSBub3MgZGFkb3Mgb3JpZ2luYWlzLiBBIGZ1bsOnw6NvIGZvaSBkZXNlbmhhIHBhcmEKcmVzb2x2ZXIgYWxndW5zIHByb2JsZW1hcyBwcmVzZW50ZXMgbm9zIGRhZG9zIG9yaWdpbmFpcy4gUG9yIGV4ZW1wbG8sCm5hcyBvIHRyZWNobyBkbyBjw7NkaWdvIGRhcyBsaW5oYXMgMTk0IGEgMjEwIGFzIG9ic2VydmHDp8O1ZXMgdmF6aWFzCihgTkFgcykgc8OjbyBzdWJzdGl0dWlkYXMgcGVsbyB2YWxvciBjb3JyZXRvIG5hIGNvbHVuYSBgZGF5X2VmZm9ydGAuIEVzc2EKY29ycmXDp8OjbyBjb250aW5udWFyw6Egc2VuZG8gcmVhbGl6YWRhIGVtIHZlcnPDtWVzIGF0dWFsaXphZGFzIGRvcyBkYWRvcyBkbwpNb25pdG9yYS4gUG9yw6ltLCBzZSBvdXRyYXMgY29sdW5hcyBhbMOpbSBkYXMgcXVlIGVzdMOjbyBzZW5kbyBjb3JyaWdpZGFzCnBvc3N1aXJlbSBvYnNlcnZhw6fDtWVzIHZhemlhcyBvcyBkYWRvcyBzZXLDo28gY2FycmVnYWRvcyBlIHRyYW5zZm9ybWFkb3MsCnBvcsOpbSBvdXRyYXMgZnVuw6fDtWVzIHBvZGVtIHRlciBvIHNldSBmdW5jaW9uYW1lbnRvIGNvbXByb21ldGlkby4gUG9yCmV4ZW1wbG8sIGZ1bsOnw7VlcyBkZSB2aXN1YWxpemHDp8OjbyBlIGRvIHBhY290ZSBgRGlzdGFuY2VgIHF1ZSBwb2RlbSBuw6NvCmZ1bmNpb25hciBkZXZpZG8gYSBhdXPDqm5jaWEgZGUgb2JzZXJ2YcOnw6NvLgoKRGVudHJlIHRvZGFzIGFzIGZ1bsOnw7VlcyBkZSBjYXJyZWdhbWVudG8gZGUgZGFkb3MsIGFwZW5hcwpgY2FycmVnYXJfZGFkb3NfYnJ1dG9zX3hsc3goKWAgY2FycmVnYSBhIGJhc2UgZGUgZGFkb3Mgb3JpZ2luYWlzIGRvCk1vbml0b3JhLCBkaXJldGFtZW50ZSBkbyBkaXJldMOzcmlvCmBkYXRhLXJhdy9tb25pdG9yYV9tYXN0b19hdmVzXzIwMjNfMDRfMDQueGxzeGAuIEFvIG1lc21vIHRlbXBvIHF1ZQpjYXJyZWdhIGUgdHJhbnNmb3JtYSBvcyBkYWRvcywgZXNzYSBmdW7Dp8OjbyBnZXJhIHVtYSB2ZXJzw6NvIGVtIHVtIGZvcm1hdG8KbWFpcyBsZXZlLCBgLnJkc2AsIG5vIGRpcmV0w7NyaW8gYGRhdGEtcmF3YAooYGRhdGEtcmF3L21vbml0b3JhX21hc3RvX2F2ZXNfMjAyM18wNF8wNC5yZHNgKS4gQSBmdW7Dp8OjbyBzZWd1aW50ZSBubwpmbHV4byBkZSB0cmFiYWxobyBjYXJyZWdhIGEgYmFzZSBhIHBhcnRpciBkZXNzYSB2ZXJzw6NvIG1haXMgbGV2ZS4gTG9nbywKc2VtcHJlIHF1ZSBob3V2ZXIgYXR1YWxpemHDp8O1ZXMgbm8gYXJxdWl2byBvcmlnaW5hbCBkZSBkYWRvcyBicnV0b3Mgw6kKbmVjZXNzw6FyaW8gaW5pY2lhciBhIHJvdGluYSBkZSBjYXJyZWdhbWVudG8gZGUgZGFkb3MgbmVjZXNzYXJpYW1lbnRlIGNvbQphIGZ1bsOnw6NvIGBjYXJyZWdhcl9kYWRvc19icnV0b3NfeGxzeCgpYC4KCiMgKipQQVJURSBJSSAtIENoZWNhZ2VtLCBzZWxlw6fDo28gZSB0cmFuc2Zvcm1hw6fDo28gZG9zIGRhZG9zKioKCiMjICoqQmFzZSBkZSBkYWRvcyBwYXJhIGFzIGFuw6FsaXNlcyoqCgpBIGJhc2UgZGUgZGFkb3MgcGFyYSBhcyBhbsOhbGlzZSB0b3JuYW0tc2UgZGlzcG9uw612ZWlzIGFvIHVzdcOhcmlvIGNvbSBvIGNhcnJlZ2FtZW50byBkbyBwYWNvdGUgY29tIG8gbm9tZSBkZSBgbW9uaXRvcmFfYXZlc19tYXN0b19mbG9yZXN0YWxgLiBQb2RlbW9zIGluc3BlY2lvbmFyIHNldSBjb250ZcO6ZG8gdXNhbmRvIGEgZnVuw6fDo28gYGdsaW1wc2VgIGRvIHBhY290ZSBgZHBseXJgLgoKYGBge3J9CiMgaW5zcGVjaW9uYXIgYSBiYXNlIGRlIGRhZG9zCmRwbHlyOjpnbGltcHNlKG1vbml0b3JhX2F2ZXNfbWFzdG9fZmxvcmVzdGFsKQpgYGAKCkEgYmFzZSBkZSBkYWRvcyBkZSBhdmVzIGUgbWFtw61mZXJvcyBkZSBtw6lkaW8gZSBncmFuZGUgcG9ydGUgZ2VyYWRhIGEgcGFydGlyIGRlIGFtb3N0cmFnZW0gcG9yIGRpc3TDom5jaWEgY29udGVtIGByIG5yb3cobW9uaXRvcmFfYXZlc19tYXN0b19mbG9yZXN0YWwpYCBvYnNlcnZhw6fDtWVzIChsaW5oYXMpIGUgYHIgbmNvbChtb25pdG9yYV9hdmVzX21hc3RvX2Zsb3Jlc3RhbClgIHZhcmnDoXZlaXMgKGNvbHVuYXMpLiBEZW50cmUgYXMgdmFyacOhdmVpcywgaMOhIGByIG1vbml0b3JhX2F2ZXNfbWFzdG9fZmxvcmVzdGFsIHw+IGRwbHlyOjo6c2VsZWN0KHdoZXJlKGlzLmZhY3RvcikpIHw+IG5jb2woKWAgcXVlIGNvbnN0aXR1ZW0gZmF0b3Jlcywgb3Ugc2VqYSwgc8OjbyB2YXJpw6F2ZWlzIGNhdGVnw7NyaWNhcyBjb20gZGlmZXJlbnRlcyBuw612ZWlzIChleC4gbm9tZV9lYSwgbm9tZV91Yywgbm9tZV9zcCksIGByIG1vbml0b3JhX2F2ZXNfbWFzdG9fZmxvcmVzdGFsIHw+IGRwbHlyOjo6c2VsZWN0KHdoZXJlKGlzLmRvdWJsZSkpIHw+IG5jb2woKWAgY29uc3RpdHVlbSB2YXJpw6F2ZWlzIG51bcOpcmljYXMgY29udMOtbnVhcyAoZXguIG51bWVyb19lYSwgZXNmb3Jjb190b3RhbCwgZGlzdGFuY2lhKSwgYHIgbW9uaXRvcmFfYXZlc19tYXN0b19mbG9yZXN0YWwgfD4gZHBseXI6OjpzZWxlY3Qod2hlcmUoaXMuaW50ZWdlcikpIHw+IG5jb2woKWAgY29uc2l0dWVtIHZhcmlhx5hlaXMgbnVtw6lyaWNhcyBpbnRlaXJhcyAoZXguICkgZSAyIHZhcmnDoXZlaXMgcXVlIHJlcHJlc2VudGFtIGRhdGFzIGUgdGVtcG9zIChleC4gZGF0YV9hbW9zdHJhZ2VtLCB0ZW1wb19jZW5zbykuIFRvZGFzIGFzIGFuw6FsaXNlcyB1dGlsaXphbSBlc3NhIGJhc2UgZGUgZGFkb3MuCgojIyAqKkZpbHRyYWdlbSBkb3MgZGFkb3MqKgoKUGFyYSBjb25kdXppciBhcyBhbsOhbGlzZXMgZGUgZXN0aW1hdGljYSBkZSBhYnVuZMOibmNpYSBlIGRlbnNpZGFkZSBkYXMgZXNww6ljaWVzLCDDqSBuZWNlc3PDoXJpbyBzZWxlY2lvbmFyIGEgZXNww6ljaWUgYWx2byBlIGEocykgVW5pZGFkZShzKSBkZSBDb25zZXJ2YcOnw6NvIG9uZGUgZXN0YShzKSBvY29ycmUobSkuIFBhcmEgaXNzbywgbyBwYWNvdGUgb2ZlcmVjZSB1bWEgZnVuw6fDo28gcGFyYSBmaWx0cmFnZW0gZSBzZWxlw6fDo28gZG9zIGRhZG9zIGNoYW1hZGEgYGZpbHRyYXJfZGFkb3MoKWAuIEEgZnVuw6fDo28gcG9zc3VpIHRyw6pzIGFyZ3VtZW50b3MsIGBub21lX3Vjc2AsIGBub21lX3Nwc2AgZSBgdmFsaWRhY2FvX29ic2AsIHBlcm1pdGUgc2VsZWNpb25hciB1bWEgcGFydGUgZG9zIGRhZG9zIGRlIGFjb3JkbyBjb20gYShzKSBVbmlkYWRlKHMpIGRlIENvbnNlcnZhw6fDo28sIGVzcMOpY2llKHMpIGUgbsOtdmVsIGRlIHZhbGlkYcOnw6NvIHRheG9uw7RtaWNvIGRlc2VqYWRvLCByZXNwZWN0aXZhbWVudGUuIMOJIHBvc3PDrXZlbCBhY2Vzc2FyIGEgZG9jdW1lbnRhw6fDo28gZGEgZnVuw6fDo28gYGZpbHRyYXJfZGFkb3MoKWAgdXNhbmRvIG8gY8OzZGlnbyBgaGVscChmaWx0cmFyX2RhZG9zKWAgb3UgYD9maWx0cmFyX2RhZG9zYC4KClBvciBjb25maWd1cmHDp8OjbywgYSBmdW7Dp8OjbyBgZmlsdHJhcl9kYWRvcygpYCByZXRvcm5hIGEgYmFzZSBkZSBkYWRvcyBgbW9uaXRvcmFfYXZlc19tYXN0b19mbG9yZXN0YWxgLgoKYGBge3J9CiMgcmV0b3JuYXIgYSBiYXNlIGRlIGRhZG9zIGNvbXBsZXRhCmZpbHRyYXJfZGFkb3MoKQpgYGAKClBhcmEgcmV0b3JuYXIgYXMgb2JzZXJ2YcOnw7VlcyBkZSB1bWEgb3UgbWFpcyBVbmlkYWRlcyBkZSBDb25zZXJ2YcOnw6NvLCBvKHMpIG5vbWUocykgZGEocykgVW5pZGFkZShzKSBkZSBDb25zZXJ2YcOnw6NvIGRldmUobSkgc2VyIGluZm9ybWFkb3MgdXNhbmRvIG8gYXJndW1lbnRvIGBub21lX3Vjc2AuCgpgYGB7cn0KIyBjb25zdWx0YXIgbyBub21lIGRhcyBVQ3MKbm9tZXNfdWNzIDwtIG1vbml0b3JhX2F2ZXNfbWFzdG9fZmxvcmVzdGFsIHw+IAogIGRwbHlyOjpkaXN0aW5jdChub21lX3VjKQoKbm9tZXNfdWNzCmBgYAoKYGBge3J9CiMgcmV0b3JuYXIgYXMgb2JzZXJ2YcOnw7VlcyBkZSB1bWEgVUMgZm9ybmVjZW5kbyBvIG5vbWUKZmlsdHJhcl9kYWRvcyhub21lX3VjcyA9ICJyZXNleF90YXBham9zX2FyYXBpdW5zIikKYGBgCgpUYW1iw6ltIMOpIHBvc3PDrXZlbCBzZWxlY2lvbmFyIHVtYSBvdSBtYWlzIFVuaWRhZGVzIGRlIENvbnNlcnZhw6fDo28gZm9ybmVjZW5kbyB1bSB2ZXRvciBkbyB0aXBvIGNhcmFjdGVyIGNvbSB1bSBvdSBtYWlzIGVsZW1lbnRvcy4KCmBgYHtyfQojIGdlcmFyIHVtIHZldG9yIGNvbnRlbmRvIG9zIG5vbWVzIGRhcyBVQ3MKbm9tZXNfdWNzIDwtIGRwbHlyOjpwdWxsKG5vbWVzX3VjcykKbm9tZXNfdWNzCmBgYAoKYGBge3J9CiMgcmV0b3JuYXIgYXMgb2JzZXJ2YcOnw7VlcyBkZSB1bWEgVUMgZm9ybmVjZW5kbyBvIG5vbWUKZmlsdHJhcl9kYWRvcyhub21lX3VjcyA9IG5vbWVzX3Vjc1sxXSkKYGBgCgpgYGB7cn0KIyByZXRvcm5hciBhcyBvYnNlcnZhw6fDtWVzIGRlIG1haXMgZGUgdW1hIFVDCmZpbHRyYXJfZGFkb3Mobm9tZV91Y3MgPSBub21lc191Y3NbMjozXSkKYGBgCgpQYXJhIHNlbGVjaW9uYXIgYXMgb2JzZXJ2YcOnw7VlcyBkZSB1bWEgb3UgbWFpcyBlc3DDqWNpZXMsIG8ocykgbm9tZShzKSBkYShzKSBlc3DDqWNpZShzKSBzZXIgaW5mb3JtYWRvcyB1c2FuZG8gbyBhcmd1bWVudG8gYG5vbWVfc3BzYC4KCmBgYHtyfQojIGNvbnN1bHRhciBvIG5vbWUgZGFzIFVDcwpub21lc19zcHMgPC0gbW9uaXRvcmFfYXZlc19tYXN0b19mbG9yZXN0YWwgfD4gCiAgZHBseXI6OmRpc3RpbmN0KG5vbWVfc3ApCgpub21lc19zcHMKYGBgCgpgYGB7cn0KIyByZXRvcm5hciBhcyBvYnNlcnZhw6fDtWVzIGRlIHVtYSBlc3DDqWNpZSBmb3JuZWNlbmRvIG8gbm9tZQpmaWx0cmFyX2RhZG9zKG5vbWVfc3BzID0gImRhc3lwcm9jdGFfY3JvY29ub3RhIikKYGBgCgpUYW1iw6ltIMOpIHBvc3PDrXZlbCBzZWxlY2lvbmFyIHVtYSBvdSBtYWlzIGVzcMOpY2llcyBmb3JuZWNlbmRvIHVtIHZldG9yIGRvIHRpcG8gY2FyYWN0ZXIgY29tIHVtIG91IG1haXMgZWxlbWVudG9zLgoKYGBge3J9CiMgZ2VyYXIgdW0gdmV0b3IgY29udGVuZG8gb3Mgbm9tZXMgZGFzIFVDcwpub21lc19zcHMgPC0gZHBseXI6OnB1bGwobm9tZXNfc3BzKQpub21lc19zcHMKYGBgCgpgYGB7cn0KIyByZXRvcm5hciBhcyBvYnNlcnZhw6fDtWVzIGRlIHVtYSBVQyBmb3JuZWNlbmRvIG8gbm9tZQpmaWx0cmFyX2RhZG9zKG5vbWVfc3BzID0gbm9tZXNfc3BzWzFdKQpgYGAKCmBgYHtyfQojIHJldG9ybmFyIGFzIG9ic2VydmHDp8O1ZXMgZGUgbWFpcyBkZSB1bWEgVUMKZmlsdHJhcl9kYWRvcyhub21lX3NwcyA9IG5vbWVzX3Nwc1tjKDMzLCAzNCldKQpgYGAKClBhcmEgc2VsZWNpb25hciBhcyBvYnNlcnZhw6fDtWVzIGRlIHVtYSBvdSBtYWlzIG9ic2VydmHDp8O1ZXMgdmFsaWRhZGFzLCBvKHMpIG7DrXZlbChpcykgdGF4b27DtG1pY28ocykgZGV2ZShtKSBzZXIgaW5mb3JtYWRvcyB1c2FuZG8gbyBhcmd1bWVudG8gYHZhbGlkYWNhb19vYnNgLgoKYGBge3J9CiMgcmV0b3JuYXIgYXMgb2JzZXJ2YcOnw7VlcyBkZSB1bWEgZXNww6ljaWUgZm9ybmVjZW5kbyBvIG5vbWUKZmlsdHJhcl9kYWRvcygKICBub21lX3NwcyA9IG5vbWVzX3Nwc1tjKDMzLCAzNCldLAogIHZhbGlkYWNhb19vYnMgPSAiZXNwZWNpZSIKKQpgYGAKCkZpbmFsbWVudGUsIHRhbWLDqW0gw6kgcG9zc8OtdmVsIHNlbGVjaW9uYXIgYXMgb2JzZXJ2YcOnw7VlcyBhIHBhcnRpciBkYShzKSBVbmlkYWRlKHMpIGRlIENvc25lcnZhw6fDo28sIGVzcMOpY2llKHMpIGUgbsOtdmVsKGlzKSB0YXhvbsO0bWljbyhzKSBkZSB2YWxpZGHDp8Ojby4KCmBgYHtyfQojIHJldG9ybmFyIGFzIG9ic2VydmHDp8O1ZXMgZGUgdW1hIGVzcMOpY2llIGZvcm5lY2VuZG8gbyBub21lCmZpbHRyYXJfZGFkb3MoCiAgbm9tZV91Y3MgPSAiZmxvbmFfZG9famFtYXJpIiwKICBub21lX3NwcyA9ICJjYWxsaWNlYnVzX2JydW5uZXVzIiwKICB2YWxpZGFjYW9fb2JzID0gImVzcGVjaWUiCikKYGBgCgojIyAqKlRyYW5zZm9ybWHDp8OjbyBkb3MgZGFkb3MqKgoKTyB1c28gZGEgZnVuw6fDo28gcXVlIGFqdXN0YSBvcyBtb2RlbG9zIGRlIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gYW9zIGRhZG9zIHBhcmEgZXN0aW1hdGl2YSBkZSBhYnVuZMOibmNpYSBlIGRlbnNpZGFkZSBkYXMgZXNww6ljaWVzIGV4aWdlbSBxdWUgb3MgZGFkb3MgYXByZXNlbnRlbSB1bSBmb3JtYXRvIGVzcGVjw61maWNvLiBBIGZ1bsOnw6NvIGB0cmFuc2Zvcm1hcl9kYWRvc19mb3JtYXRvX0RzaXRhbmNlKClgIHJlYWxpemEgYSBzZWxlw6fDo28gZGFzIHZhcmnDoXZlaXMgZSBhcyB0cmFuc2Zvcm1hw6fDtWVzIG5lY2Vzc8OhcmlhcyBwYXJhIGRlaXhhciBvcyBkYWRvcyBwcm9udG9zIHBhcmEgc2VyZW0gYW5hbGlzYWRvcy4gCgpQcmltZWlyYW1lbnRlLCDDqSBuZWNlc3PDoXJpbyBjcmlhciB1bSB0YWJlbGEgZGUgZGFkb3MgY29udGVuZG8gYXMgb2JzZXJ2YcOnw7VlcyBkYSBlc3DDqWNpZSBxdWUgc2UgZGVzZWphIGVzdGltYXIgYSBkZW5zaWRhZGUuCgpgYGB7cn0KZGFzeV9jcm9jIDwtIGZpbHRyYXJfZGFkb3MoCiAgbm9tZV9zcHMgPSAiZGFzeXByb2N0YV9jcm9jb25vdGEiLAogIHZhbGlkYWNhb19vYnMgPSAiZXNwZWNpZSIKKQpgYGAKCgpgYGB7cn0KIyB0cmFuc2Zvcm1hciBvcyBkYWRvcyBwYXJhIG8gZm9ybWF0byBkbyBEaXN0YW5jZQpkYXN5X2Nyb2NfY29tX3JlcCA8LSB0cmFuc2Zvcm1hcl9kYWRvc19mb3JtYXRvX0Rpc3RhbmNlKGRhc3lfY3JvYykKCmRhc3lfY3JvY19jb21fcmVwCmBgYAoKQSBmdW7Dp8OjbyB0YW1iw6ltIHBlcm1pdGUgZWxpbWluYXIgYXMgYW1vc3RyYWdlbnMgcmVwZXRpZGFzIHJlYWxpemFkYXMgZW0gdW1hIG1lc21hIGVzdGHDp8OjbyBkbyBhbm8sIHNlbGVjaW9uYW5kbyBhcGVuYXMgbyBkaWEgZW0gcXVlIGZvaSByZWdpc3RyYWRvIG8gbWFpb3IgbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBhcmEgdW1hIGRldGVybWluYWRhIGVzdGHDp8OjbyBlIGFuby4gUGFyYSBlbGltaW5hciBhcyBhbW9zdHJhZ2VucyByZXBldGlkYXMsIGJhc3RhIHV0aWxpemFyIG8gYXJndW1lbnRvIGBhbW9zdHJhc19yZXBldGlkYXMgPSBGQUxTRWAuCgpgYGB7cn0KZGFzeV9jcm9jX3NlbV9yZXAgPC0gdHJhbnNmb3JtYXJfZGFkb3NfZm9ybWF0b19EaXN0YW5jZSgKICBkYWRvcyA9IGRhc3lfY3JvYywKICBhbW9zdHJhc19yZXBldGlkYXMgPSBGQUxTRQopCgpkYXN5X2Nyb2Nfc2VtX3JlcApgYGAKCgojICoqUEFSVEUgSUlJIC0tIEV4cGxvcmFuZG8gZSBzZWxlY2lvbmFuZG8gb3MgZGFkb3MgcGFyYSBhcyBhbsOhbGlzZXMqKgoKQXByZXNlbnRhbW9zIGFiYWl4byB1bSBjb25qdW50byBkZSBmZXJyYW1lbnRhcyBxdWUgcGVybWl0ZSBkaXZlcnNhcwpmb3JtYXMgZGUgZXhwbG9yYXIgdG9kbyBvIGNvbmp1bnRvIGRlIGRhZG9zLgoKIyMgKipJbmZvcm1hw6fDtWVzIEdlcmFpcyBzb2JyZSBvIEJhbmNvIGRlIERhZG9zKioKCiMjIyBUb3RhbCBVbmlkYWRlcyBkZSBDb25zZXJ2YcOnw6NvIGFtb3N0cmFkYXMKCmBgYHtyIG5fZGVfdWNzfQojIGNvbnRhciBuw7ptZXJvIHRvdGFsIGRlIFVDJ3MgCm5fdWNzIDwtIGNvbnRhcl9uX3VjKCkKbl91Y3MKYGBgCgpPcyBkYWRvcyBzw6NvIHByb3ZlbmllbnRlcyBkZSBgciBuX3Vjc2AgdW5pZGFkZXMgZGUgY29uc2VydmHDp8OjbyBhbyB0b2RvLgoKIyMjIE7Dum1lcm8gZGUgdW5pZGFkZXMgZGUgY29uc2VydmHDp8OjbyBhbW9zdHJhZGFzIGVtIGNhZGEgYW5vCgpgYGB7ciwgZWNobz1GQUxTRX0KIyBnZXJhciB0YWJlbGEgY29tIG8gbsO6bWVybyBkZSB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGFtb3N0cmFkYXMgZW0gY2FkYSBhbm8Kbl91Y3NfYW5vIDwtIGNvbnRhcl9uX3VjX2FubygpCm5fdWNzX2FubwpgYGAKCkdlcmFyIGZ1bsOnw6NvIHBhcmEgdGFiZWxhIGRpbsOibWljYS4KCmBgYHtyfQpnZXJhcl90YWJkaW4obl91Y3NfYW5vKQpgYGAKCiMjIyBVbmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGFtb3N0cmFkYXMgZW0gdW0gbWFpb3IgbsO6bWVybyBkZSBhbm9zCgpgYGB7cn0Kbl9hbm9fdWMgPC0gY29udGFyX25fYW5vX3VjKCkKbl9hbm9fdWMgIApgYGAKCmBgYHtyfQpnZXJhcl90YWJkaW4obl9hbm9fdWMpCmBgYAoKIyMjIFRvdGFsIGRlIG9ic2VydmHDp8O1ZXMgcG9yIFVuaWRhZGUgZGUgQ29uc2VydmHDp8OjbwoKYGBge3J9CiMgY29udGFyIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwb3IgVUMKbl9vYnNfdWMgPC0gY29udGFyX25fb2JzX3VjKCkKbl9vYnNfdWMKYGBgCgpgYGB7cn0KIyBnZXJhciB0YWJkaW4KZ2VyYXJfdGFiZGluKG5fb2JzX3VjKQpgYGAKCmBgYHtyfQojIGdlcmFyIHRhYmRpbgpnZXJhcl90YWJkaW4obl9vYnNfdWMpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTIwLCBmaWcuYWxpZ249J2NlbnRlcid9CiMgcGxvdGFyIG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBVQwpwbG90YXJfbl9vYnNfdWNfaW50ZXJhdGl2byhuX29ic191YykKYGBgCgojIyMgTsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHJlYWxpemFkYXMgcG9yIFVDIGVtIGNhZGEgYW5vCgpgYGB7cn0Kbl9vYnNfdWNfYW5vIDwtIGNvbnRhcl9uX29ic191Y19hbm8oKQpuX29ic191Y19hbm8KYGBgCgpUYWJlbGEgaW50ZXJhdGl2YSBwYXJhIGNvbnN1bHRhciBxdWFudGFzIG9ic2VydmHDp8O1ZXMgZm9yYW0gcmVhbGl6YWRhcwpwb3IgYW5vIGVtIGNhZGEgVUMKCmBgYHtyfQpnZXJhcl90YWJkaW4obl9vYnNfdWNfYW5vKQpgYGAKCiMjIyBUb3RhbCBkZSBvYnNlcnZhw6fDtWVzIHZhbGlkYWRhcyBwb3IgbsOtdmVsIHRheG9uw7RtaWNvCgpFc3NhcyBvcGVyYcOnw7VlcyBzw6NvIHJlYWxpemFkYXMgc29icmUgYSB0YWJlbGEgZGUgZGFkb3MgYGRhZG9zX2NvbXBsZXRvc2AKcG9pcyBvcyBkYWRvcyBxdWUgZm9yYW0gdHJhbnNmb3JtYWRvcyBwYXJhIG8gZm9ybWF0byBkbyBkaXN0YWNlIG5vIFIgbsOjbwpwb3NzdWVtIGEgY29sdW5hIGB2YWxpZGF0aW9uYCwgbmVjZXNzw6FyaWEgcGFyYSBlc3NhcyBvcGVyZWHDp8O1ZXMuIE1haXMgYQpmcmVudGUgbyBwcm9jZWRpbWVudG8gZGUgY29tbyBvYnRlciBvcyBkYWRvcyBzZWxlY2lvbmFkb3MgZQp0cmFuc2Zvcm1hdG9zIHBhcmEgbyBmb3JtYXRvIGRhcyBhbsOhbGlzZXMgc2Vyw6EgZGVtb25zdHJhZG8uCgpgYGB7cn0KIyBjb250YXIgb2JzZXJ2YcOnw7VlcyB2YWxpZGFkYXMgYW8gbsOtdmVsIGRlIGVzcMOpY2llCm5fb2JzX3ZhbGlkYWRhcyA8LSBjb250YXJfbl9vYnNfdmFsaWRhZGFzKCkKbl9vYnNfdmFsaWRhZGFzCmBgYAoKRm9yYW0gc2VsZWNpb25hZGFzIGFwZW5hcyBhcyBvYnNlcnZhw6fDtWVzIHZhbGlkYWRhcyBhbyBuw612ZWwgZGUgZXNww6ljaWUsCnNvbWFuZG8gdW0gdG90YWwgYHIgbl9vYnNfdmFsaWRhZGFzWzFdYCBvYnNlcnZhw6fDtWVzLgoKYGBge3J9CiMgZ2VyYXIgZ3LDoWZpY28gY29tIG7Dum1lcm8gb2JzZXJ2YcOnw7VlcyB2YWxpZGFkYXMgcGFyYSBjYWRhIG7DrXZlbCB0YXhvbsO0bWljbwpwbG90YXJfbl9vYnNfdmFsaWRhZGFzX2ludGVyYXRpdm8obl9vYnNfdmFsaWRhZGFzKQpgYGAKCiMjIyBUb3RhbCBkZSBlc3DDqWNpZXMgcmVnaXN0cmFkYXMKCmBgYHtyfQpuX3NwIDwtIGNvbnRhcl9uX3NwKCkKbl9zcApgYGAKCkF0w6kgYXF1aSB0ZW1vcyBkYWRvcyBwYXJhIGByIG5fc3BgIGVzcMOpY2llcy4KCiMjKipTdWZpY8OqbmNpYSBBbW9zdHJhbCoqCgoqKk7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyoqCgpQYXJhIHF1ZSBvIG3DqXRvZG8gZGUgYW7DoWxpc2UgcG9yIGRpc3TDom5jaWEgcG9zc2Egc2VyIHV0aWxpemFkbyBwYXJhCmVzdGltYXRpdmFzIGJhc2VhZGFzIGVtIG1vZGVsb3MsIHPDo28gcmVjb21lbmRhZGFzIHF1YW50aWRhZGVzIG3DrW5pbWFzIGRlCm9ic2VydmHDp8O1ZXMgZSBkZSB0cmFuc2VjdG9zIChVbmlkYWRlcyBBbW9zdHJhaXMpLiBTZWd1bmRvIEJVQ0tMQU5EIGV0LgphbC4gKDIwMTUpLCBPIG7Dum1lcm8gbcOtbmltbyBzdWdlcmlkbyBkZSBhbmltYWlzIG91IGdydXBvcyDDqSBkZSAqKjYwIC0tCjgwIGFuaW1haXMgKG91IGdydXBvcykqKiBxdWFuZG8gYSBhbW9zdHJhZ2VtIMOpIGZlaXRhIHBlbG8gbcOpdG9kbyBkb3MKdHJhbnNlY3RvcyBsaW5lYXJlcy4gw4kgcG9zc8OtdmVsIHV0aWxpemFyIG7Dum1lcm9zIG1lbm9yZXMgcXVlIGVzdGVzIHBhcmEKcmVhbGl6YXIgYXMgYW7DoWxpc2VzLCBwb3LDqW0gZGV2ZS1zZSB0ZXIgbyBjdWlkYWRvIGRlIHZlcmlmaWNhciBzZSBhcwpmdW7Dp8O1ZXMgZGUgZGV0ZWPDp8OjbyBlc3TDo28gYmVtIG1vZGVsYWRhcy4gRXN0ZXMgbsO6bWVyb3MgcmVjb21lbmRhZG9zIHNlCmFwbGljYW0gYSBjYWRhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gYSBzZXIgbW9kZWxhZGEuIEFzc2ltLCBxdWFuZG8gc2UKcHJldGVuZGUgZXN0cmF0aWZpY2FyIG9zIGRhZG9zLCBkaXZpZGluZG8tb3MgZW0gc3ViY29uanVudG9zLCBzZWphIHBvcgpyZWdpw6NvIGdlb2dyw6FmaWNhLCBzZWphIHBvciBwZXLDrW9kbyBhbW9zdHJhbCwgw6kgbmVjZXNzw6FyaW8gdGVyIHVtCmN1aWRhZG8gcGFyYSBxdWUgYSBzdWZpY2nDqm5jaWEgYW1vc3RyYWwgc2UgbWFudGVuaGEgZGVudHJvIGRvcwpzdWJjb25qdW50b3MuCgoKKipSw6lwbGljYXMgZSByZXBldGnDp8O1ZXMqKgoKTyBuw7ptZXJvIG3DrW5pbW8gZGUgKipyw6lwbGljYXMgcGFyYSBvcyB0cmFuc2VjdG9zIGRldmUgc2VyIGRlIDEwLTIwKiosIG8KcXVlIGRldmUgYXVtZW50YXIgcGFyYSBlc3DDqWNpZXMgY3VqYXMgcG9wdWxhw6fDtWVzIHPDo28gZGlzdHJpYnXDrWRhcyBlbQptYW5jaGFzIEJVQ0tMQU5EIGV0LiBhbC4gKDIwMTUpLiBPIG7Dum1lcm8gZGUgcsOpcGxpY2FzIHJlYWlzIHBhcmEgY2FkYQplc3DDqWNpZSDDqSBvIG7Dum1lcm8gZGUgdHJhbnNlY3RvcywgcXVlIHJlY2ViZW0gb3Mgbm9tZXMgZGFzIGVzdGHDp8O1ZXMKYW1vc3RyYWlzIGVtIGNhZGEgVW5pZGFkZSBkZSBjb25zZXJ2YcOnYcO1LgoKVW0gb3V0cm8gYXNwZWN0byBxdWUgw6kgbmVjZXNzw6FyaW8gb2JzZXJ2YXIgw6kgbyBuw7ptZXJvIGRlIHJlcGV0acOnw7VlcywgcXVlCnRlcsOhIGltcGFjdG8gdGFudG8gc29icmUgbyBlc2ZvcsOnbyBxdWFudG8gc29icmUgYSBzdWZpY2nDqm5jaWEgYW1vc3RyYWwuClVtYSBkYXMgbGltaXRhw6fDtWVzIGRvcyBkYWRvcyBkbyBQcm9ncmFtYSBNb25pdG9yYSDDqSBvIHBlcXVlbm8gbsO6bWVybyBkZQpyw6lwbGljYXMgcG9yIFVuaWRhZGUgZGUgQ29uc2VydmHDp8OjbyBlIG11aXRhcyByZXBldGnDp8O1ZXMgcGFyYSBhcyBtZXNtYXMKZXN0YcOnw7VlcyBhbW9zdHJhaXMuIE8gZXhjZXNzbyBkZSByZXBldGnDp8O1ZXMsIGVzcGVjaWFsbWVudGUgZW0gdW0gbWVzbW8KcGVyw61vZG8gYW1vc3RyYWwsIGNvbXByb21ldGUgYSBwcmVtaXNzYSBkZSBpbmRlcGVuZMOqbmNpYSBlbnRyZSBhcwpvYnNlcnZhw6fDtWVzLiBBbMOpbSBkaXNzbywgYWNhYmEgdGVuZG8gdW0gZWZlaXRvIGRlIGluZmxhciBvIGVzZm9yw6dvCmFtb3N0cmFsIGUgYSDDoXJlYSBjb2JlcnRhIHBlbGEgYW1vc3RyYWdlbSwgbyBxdWUgcHJlanVkaWNhIGFzCmVzdGltYXRpdmFzIGRlIGRlbnNpZGFkZS4KCkFwZW5hcyBwYXJhIGlsdXN0YXIsIHBhcmEgb3MgZGFkb3MgZGEgY3V0aWEgKkRhc3lwcm9jdGEgY3JvY29ub3RhKiBkYQpSZXNleCBUYXBhasOzcy1BcmFwaW51bnMsIGEgRXN0YcOnw6NvIEFtb3N0cmFsIEJvaW0gZm9pIHBlcmNvcnJpZGEgZHVyYW50ZQo3MCBkaWFzIGRlIGFtb3N0cmFnZW0uIElzc28gc2lnbmlmaWNhIHF1ZSBhanVzdGFuZG8gbyBjb21wcmltZW50byBkbwp0cmFuc2VjdG8gZGUgNSBrbSBwZWxvIG7Dum1lcm8gZGUgcmVwZXRpw6fDtWVzLCBvIGVzZm9yw6dvIGFtb3N0cmFsIHBhc3NvdQpwYXJhIDM1MCBrbS4gQSDDoXJlYSBjb2JlcnRhIGF1bWVudG91IGVtIDcweCwgbyBxdWUgdGVyw6EgY29uc2VxdcOqbmNpYXMKc29icmUgYSBlc3RpbWF0aXZhIGRlbnNpZGFkZSwgcXVlIHRlbmRlcsOhIGEgc2VyIHN1YmVzdGltYWRhLiBBbMOpbSBkaXNzbywKbyBjb2VmaWNpZW50ZSBkZSB2YXJpYcOnw6NvIGRhcyBlc3RpbWF0aXZhcyBkZSB0YXhhIGRlIGVuY29udHJvLAphYnVuZMOibmNpYSBlIGRlbnNpZGFkZSB0YW1iw6ltIHRlbmRlcsOjbyBhIGF1bWVudGFyIHBlbG8gZWZlaXRvIGRhCnZhcmlhw6fDtWVzIHRlbXBvcmFpcyBlbnRyZSBhcyBhbW9zdHJhZ2Vucy4KClBhcmEgbGlkYXIgY29tIG8gZXhjZXNzbyBkZSByZXBldGnDp8O1ZXMsIGltcGxlbWVudGFtb3MgdW0gZmx1eG8gZGUKdHJhYmFsaG8gb25kZSByZWR1emltb3MgbyBuw7ptZXJvIGRlIHJlcGV0acOnw7VlcywgbWFudGVuZG8gc29tZW50ZSB1bSBkaWEKZGUgYW1vc3RyYWdlbSBjb20gbyBtYWlvciBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIHBlcsOtb2RvCmFtb3N0cmFsIChQYXJ0ZSBWLCBGbHV4byAyKS4KCgoKIyMjIyBOw7ptZXJvIHRvdGFsIGRlIG9ic2VydmHDp8O1ZXMgcG9yIGVzcMOpY2llCgpgYGB7ciwgZmlnLmhlaWdodD0yMH0KIyBjb250YXIgdG90YWwgc3AKbl9vYnNfc3AgPC0gY29udGFyX25fb2JzX3NwKCkKbl9vYnNfc3AKYGBgCgpgYGB7cn0KIyBnZXJhciB0YWJlbGEgZGluw6JtaWNhIGNvbSBvIG7Dum1lcm8gdG90YWwgZGUgb2JzZXZhw6fDtWVzIHBvciBlc3DDqWNpZQpnZXJhcl90YWJkaW4obl9vYnNfc3ApCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9MjB9CiMgcGxvdGFyIG8gbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yIFVDCnBsb3Rhcl9uX29ic19zcF9pbnRlcmF0aXZvKG5fb2JzX3NwKQpgYGAKCiMjIyMgTsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBhcmEgY2FkYSBlc3DDqWNpZSBwb3IgdW5pZGFkZSBkZSBjb25zZXJ2YcOnw6NvCgpgYGB7cn0KIyBnZXJhciB0YWJlbGEgY29tIG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBlc3DDqWNpZSBlIHBvciBVQwpuX29ic19zcF91YyA8LSBjb250YXJfbl9vYnNfc3BfdWMoKQpuX29ic19zcF91YwpgYGAKCmBgYHtyfQpnZXJhcl90YWJkaW4obl9vYnNfc3BfdWMpCmBgYAoKIyMjIyBOw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llcyBwb3IgYW5vCgpgYGB7cn0Kbl9vYnNfc3BfYW5vIDwtIGNvbnRhcl9uX29ic19zcF9hbm8oKQpuX29ic19zcF9hbm8KYGBgCgpUYWJlbGEgaW50ZXJhdGl2YSBwYXJhIGNvbnN1bHRhciBxdWFudGFzIG9ic2VydmHDp8O1ZXMgZm9yYW0gcmVhbGl6YWRhcwpwYXJhIGNhZGEgZXNww6ljaWUgZW0gY2FkYSBhbm8KCmBgYHtyfQpnZXJhcl90YWJkaW4obl9vYnNfc3BfYW5vKQpgYGAKCiMjIyMgTsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBhcmEgY2FkYSBlc3DDqWNpZXMgcG9yIFVDIGUgcG9yIGFubwoKYGBge3J9Cm5fb2JzX3NwX3VjX2FubyA8LSBjb250YXJfbl9vYnNfc3BfdWNfYW5vKCkKbl9vYnNfc3BfdWNfYW5vCmBgYAoKVGFiZWxhIGludGVyYXRpdmEgcGFyYSBjb25zdWx0YXIgcXVhbnRhcyBvYnNlcnZhw6fDtWVzIGZvcmFtIHJlYWxpemFkYXMKcGFyYSBjYWRhIGVzcMOpY2llIGVtIGNhZGEgYW5vCgpgYGB7cn0KZ2VyYXJfdGFiZGluKG5fb2JzX3NwX3VjX2FubykKYGBgCgojIyMjIE7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwYXJhIGNhZGEgZXNww6ljaWVzIHBvciBVQywgcG9yIGVzdGHDp8OjbyBkbyBhbm8gZSBwb3IgYW5vCgpgYGB7cn0Kbl9vYnNfc3BfdWNfZXN0YWNhb19hbm8gPC0gY29udGFyX25fb2JzX3NwX3VjX2VzdGFjYW9fYW5vKCkKbl9vYnNfc3BfdWNfZXN0YWNhb19hbm8KYGBgCgpgYGB7cn0KZ2VyYXJfdGFiZGluKG5fb2JzX3NwX3VjX2VzdGFjYW9fYW5vKQpgYGAKCiMjI0lOQ0xVSVIgKipSw6lwbGljYXMgZSBSZXBldGnDp8O1ZXMqKgoKIyMjIyBOw7ptZXJvIGRlIFVDcyBwYXJhIGNhZGEgZXNww6ljaWUKCiMjIyMgTsO6bWVybyBkZSByw6lwbGljYXMgKGVzdGHDp8O1ZXMgYW1vc3RyYWlzKSBwYXJhIGNhZGEgZXNww6ljaWUKCiMjIyMgTsO6bWVybyBkZSByw6lwbGljYXMgKGVzdGHDp8O1ZXMgYW1vc3RyYWlzKSBwYXJhIGNhZGEgZXNww6ljaWUgcG9yIFVDCgojIyMjTsO6bWVybyBkZSByZXBldGnDp8O1ZXMgcG9yIGVzdGHDp8OjbyBhbW9zdHJhbCBwYXJhIGNhZGEgZXNww6ljaWUKCiMjIyNOw7ptZXJvIGRlIHJlcGV0acOnw7VlcyBwb3IgZXN0YcOnw6NvIGFtb3N0cmFsIHBvciBVQyBwYXJhIGNhZGEgZXNww6ljaWUKCiMjIyNOw7ptZXJvIGRlIHJlcGV0acOnw7VlcyBwb3IgZXN0YcOnw6NvIGFtb3N0cmFsIHBvciBVQyBwYXJhIGNhZGEgZXNww6ljaWUKcG9yIGFubwoKIyMjI07Dum1lcm8gZGUgcmVwZXRpw6fDtWVzIHBvciBlc3Rhw6fDo28gYW1vc3RyYWwgcG9yIFVDIHBhcmEgY2FkYSBlc3DDqWNpZQpwb3IgcGVyw61vZCBhbW9zdHJhbCAoZXN0YcOnw7VlcyBkbyBhbm8vYW5vKQoKIyMgKipEaXN0cmlidWnDp8OjbyBkYXMgZnJlcXXDqm5jaWFzIGRlIG9ic2VydmHDp8O1ZXMgcGVsYSBkaXN0w6JuY2lhKioKCkFsZ3VtYXMgc2l0dWHDp8O1ZXMgYW1vc3RyYWlzIHBvZGVtIGxldmFyIGEgZWZlaXRvcyBpbmRlc2VqYWRvcyBuYQpkaXN0cmlidWnDp8OjbyBkb3MgZGFkb3MsIGNvbWVudGFkYXMgYSBzZWd1aXIuIFBhcmEgZXhwbG9yYXIgYQpkaXN0cmlidWnDp8OjbyBkb3MgZGFkb3MgcmVjb21lbmRhbW9zIHRhbWLDqW0gbyB1c28gZG8KYGFwcF9kaXN0YW5jYV9pbnRlcmF0aXZvLlJgIGVtIGBwaXBlcjNkX21vbml0b3JhX2Zsb3Jlc3RhbFxhcHBzYC4KCkVtcGlsaGFtZW50byBkYXMgb2JzZXJ2YcOnw7VlcyAoaGVhcGluZykgLS0gb2NvcnJlIHF1YW5kbyB2YWxvcmVzIGRhcwpkaXN0w6JuY2lhcyBwZXJwZW5kaWN1bGFyZXMgc8OjbyBhcnJlZG9uZGFkb3MuIE8gZWZlaXRvIMOpIHVtIGFjw7ptdWxvIGRlCm9ic2VydmHDp8O1ZXMgc29icmUgYSBtZXNtYSBkaXN0w6JuY2lhLCBxdWUgY29ycmVzcG9uZGUgYSB1bSB2YWxvciByZWRvbmRvLgpVbSB0aXBvIGVzcGVjw61maWNvIGRlIGVtcGlsaGFtZW50byDDqSBxdWFuZG8gZWxlIHNlIGTDoSBzb2JyZSBhIGRpc3TDom5jaWEKemVybywgdGFtYsOpbSBjaGFtYWRvIGRlIHBpY28gcHLDs3hpbW8gYSBkaXN0w6JuY2lhIHplcm8gKHNwaWtlIG5lYXIgemVybwpkaXN0YW5jZSkuIEVzc2UgdGlwbyBkZSBlZmVpdG8gZm9pIG9ic2VydmFkbyBjb20gZnJlcXXDqm5jaWEgbm9zIGRhZG9zIGRvClByb2dyYW1hIE1vbml0b3JhLiBVbWEgZGFzIGVzdHJhdMOpZ2lhcyBwYXJhIHJlZHXDp8OjbyBkb3MgZWZlaXRvcyBkZQplbXBpbGhhbWVudG8gw6kgYWdydXBhciBvcyBkYWRvcyBkZSBkaXN0w6JuY2lhIGVtIGludGVydmFsb3MuCkltcGxlbWVudGFtb3MgZXNzYSBlc3RyYXTDqWdpYSBuYSBQYXJ0ZSBWIC0tIEZsdXhvIDMuCgpNb3ZpbWVudG8gZGUgcmVzcG9zdGEgYW8gb2JzZXJ2YWRvciAtLSBvcyBhbmltYWlzIHBvZGVtIHNlciByZXBlbGlkb3Mgb3UKYXRyYcOtZG9zIHBlbG8gb2JzZXJ2YWRvci4gUGFyYSBhbmltYWlzIHF1ZSBhcHJlc2VudGFtIHJlc3Bvc3RhIGRlIGZ1Z2EKZW0gcmVsYcOnw6NvIGFvIG9ic2VydmFkb3IgbyBlZmVpdG8gbm8gaGlzdG9ncmFtYSBkZSBmcmVxdcOqbmNpYXMgw6kgdW0KYXVtZW50byBuYXMgb2JzZXJ2YcOnw7VlcyBlbSBkaXN0w6JuY2lhcyBpbnRlcm1lZGnDoXJpYXMuIFBhcmEgYW5pbWFpcyBxdWUKc8OjbyBhdHJhw61kb3MgcGVsbyBvYnNlcnZhZG9yLCBhIHRlbmTDqm5jaWEgw6kgZGUgdW0gYXVtZW50byBuYXMKb2JzZXJ2YcOnw7VlcyBuYXMgZGlzdMOibmNpYXMgcHLDs3hpbWFzIGEgemVybywgbyBxdWUgdGFtYsOpbSBwb2RlIGdlcmFyIG8KcGFkcsOjbyBkZSBwaWNvIHByw7N4aW1vIGEgemVyby4gTyBlZmVpdG8gZGVzc2UgdmnDqXMgc29icmUgYXMgb2JzZXJ2YcOnw7VlcwrDqSBlbnZpZXNhciB0YW1iw6ltIG9zIG1vZGVsb3MgYWp1c3RhZG9zIChmb3JtYXRvIGRhIGN1cnZhKSwgYXMKcHJvYmFiaWxpZGFkZXMgZGUgZGV0ZcOnw6NvIGUgYWJ1bmTDom5jaWFzIGVzdGltYWRhcyBlbSBjYWRhIGZhaXhhIGRlCmRpc3TDom5jaWEuCgpTdXBlcmRpc3BlcnPDo28gLS0gw6kgdW0gZWZlaXRvIGNhdXNhZG8gcXVhbmRvIGFzIG9ic2VydmHDp8O1ZXMgbsOjbyBzw6NvCmluZGVwZW5kZW50ZXMsIGNvbW8gbm8gY2FzbyBkYXMgcmVwZXRpw6fDtWVzIGVtIHVtIG1lc21vIHRyYW5zZWN0by4gTwplZmVpdG8gbm8gaGlzdG9ncmFtYSBzw6NvIHBpY29zIGVtIGFsZ3VtYXMgZGlzdMOibmNpYXMgb3UgcmVkdcOnw7VlcwphYnJ1cHRhcyBlbSBvdXRyYXMgKEZpZ3VyYSBYKS4gTyBleGNlc3NvIGRlIHJlcGV0acOnw7VlcyB0YW1iw6ltIGZvaSB1bWEKbGltaXRhw6fDo28gZW5jb250cmFkYSBub3MgZGFkb3MgZG8gUHJvZ3JhbWEgTW9uaXRvcmEuIEltcGxlbWVudGFtb3MgdW1hCmVzdHJhdMOpZ2lhIHBhcmEgcmVkdXppciBvIG7Dum1lcm8gZGUgcmVwZXRpw6fDtWVzIG1hbnRlbmRvIHNvbWVudGUgYSBkYXRhCmNvbSBvIG1haW9yIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwb3IgcGVyw61vZG8gYW1vc3RyYWwgbmEgUGFydGUgViAtCkZsdXhvIDIuCgpQYXJhIG1haW9yZXMgZGV0YWxoZXMsIHZlciBmaWd1cmFzIG5vIE1hdGVyaWFsIGRlIFN1cG9ydGUgZGUgQXNwZWN0b3MKVGXDs3JpY29zLgoKYGBge3IgZGlzdHJpYnVpY2FvX2RzaXRhbmNpYSwgd2FybmluZz1GQUxTRX0KIyBnZXJhciBvIGdyw6FmaWNvIGV4cGxvcmF0w7NyaW8gZGEgZGlzdHJpYnVpw6fDo28gZGUgZGlzdMOibmNpYXMgcGVycGVuZGljdWxhcmVzIHBhcmEgYSBlc3DDqWNpZXMgRGFzeXJvY3RhIGNyb2Nvbm90YSBuYSBSZXNleCBUYXBhasOzcy1BcmFwaXVucwpmaWcgPC0gZGFkb3NfZmlsdHJhZG9zIHw+CiAgIyBleGNsdWlyIE5BJ3MgZGEgdmFyacOhdmVsIGRpc3RhbmNlCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IAogIHBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8oKQoKZmlnCmBgYAoKIyMgSU5DTFVJUiAqKkRpc3RyaXVidWnDp8OjbyBkYXMgY292YXJpw6F2ZWlzIHBlbGEgZGlzdMOibmNpYSoqCgpVbWEgYm9hIGVzY29saGEgZGUgY292YXJpw6F2ZWlzIHBhc3NhIHBvciB1bSBib20gcHJvY2Vzc28gZXhwbG9yYXTDs3Jpbwpkb3MgZGFkb3MuIMOJIGltcG9ydGFudGUgYXZhbGlhciBjb21vIGZhdG9yZXMgYW1iaWVudGFpcyBvdSBhbW9zdHJhaXMKcG9kZW0gaW5mbHVlbmNpYXIgZGUgZm9ybWEgc2lnbmlmaWNhdGl2YSBhIGRldGVjdGFiaWxpZGFkZSBkb3MgYW5pbWFpcy4KUGFyYSBhdmFsaWFyIGVzc2UgcG9zc8OtdmVsIGVmZWl0bywgw6kgbmVjZXNzw6FyaW8gb2xoYXIgYSBkaXN0cmlidWnDp8OjbyBkYXMKY292YXJpw6F2ZWlzIGVtIHJlbGHDp8OjbyDDoCBkaXN0w6JuY2lhLiBTZSBob3V2ZXIgdmnDqXMgZGFzIGNvdmFyacOhdmVpcyBlbQpyZWxhw6fDo28gw6EgZGlzdMOibmNpYSwgw6kgcG9zc8OtdmVsIHF1ZSBlc3RlamFtIGluZmx1ZW5jaWFuZG8gbmEKZGV0ZWN0YWJpbGlkYWRlIHRhbWLDqW0uIFBvciBleGVtcGxvLCBzZSBhIGF0aXZpZGFkZSBkZSB1bSBhbmltYWwgw6kKaW5mbHVlbmNpYWRhIHBlbG8gaG9yw6FyaW8sIMOpIHBvc3PDrXZlbCBxdWUgZWxlIHNlamEgZGV0ZWN0YWRvIGNvbSBtYWlvcgpmcmVxdcOqbmNpYSBlbSBkaXN0w6NuY2lhcyBtYWlvcmVzIG5vIHNldSBob3LDoXJpbyBkZSBtYWlvciBhdGl2aWRhZGUuCgpQYXJhIG9zIGRhZG9zIGRvIFByb2dyYW1hIE1vbml0b3JhLCB1bWEgZGFzIHByaW5jaXBhaXMgY292YXJpw6F2ZWlzIGEgc2VyCmNvbnNpZGVyYWRhIMOpIG8gdGFtYW5obyBkbyBncnVwbyAocywgcXVlIGRldmUgc2VyIGNoYW1hZGEgZGUgc2l6ZSBwYXJhIG8KcGFjb3RlIERpc3RhbmNlKS4gVW0gZG9zIGVmZWl0b3MgZXNwZXJhZG9zIHBhcmEgZXNww6ljaWVzIHF1ZSBmb3JtYW0KZ3J1cG9zIMOpIG8gY2hhbWFkbyB2acOpcyBkZSB0YW1hbmhvLiBBIHRlbmTDqm5jaWEgw6kgcXVlIGEgcGVxdWVuYXMKZGlzdMOibmNpYXMgdG9kb3Mgb3MgZ3J1cG9zIHNlamFtIGRldGVjdMOhdmVpcywgbWFzIHNvbWVudGUgb3MgZ3J1cG9zCm1haW9yZXMgc2Vyw6NvIGRldGVjdGFkb3MgYSBkaXN0w6JuY2lhcyBtYWlvcmVzLgoKIyAqKlBBUlRFIElWIC0tIEFqdXN0YW5kbyBvcyBtb2RlbG9zKioKCiMjIEZsdXhvIGRlIGFuw6FsaXNlIGRvcyBkYWRvczoKCkEgc2VndWlyLCBhcHJlc2VudGFtb3MgbyBmbHV4byBkZSBhbsOhbGlzZSBkb3MgZGFkb3MgcXVlIGVudm9sdmUgYSBmYXNlCmV4cGxvcmF0w7NyaWEsIHRydW5jYW1lbnRvLCBhanVzdGUgZSBhdmFsaWHDp8OjbyBkZSBtb2RlbG9zIGUgZXN0aW1hdGl2YXMKZGUgYWJ1bmTDom5jaWEgZSBkZW5zaWRhZGUgcGFyYSBhcyBlc3DDqWNpZXMgcXVlIHNlbGVjaW9uYW1vcyBjb21vIG1vZGVsby4KVXNhbW9zIGNvbW8gY3JpdMOpcmlvcyBkZSBzZWxlw6fDo28gdGFudG8gbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yClVuaWRhZGUgZGUgQ29uc2VydmHDp8OjbyBxdWFudG8gYSBkaXN0cmlidWnDp8OjbyBkYXMgZnJlcXXDqm5jaWFzIGRlCm9ic2VydmHDp8Ojbywgbm9zIGNhc29zIGVtIHF1ZSBpc3NvIGZvaSBwb3Nzw612ZWwuIERlIGZvcm1hIGdlcmFsLCBhcwplc3DDqWNpZXMgY29tIG7Dum1lcm8gc2F0aXNmYXTDs3JpbyBkZSBvYnNlcnZhw6fDtWVzICgkPiQ2MCksIGFwcmVzZW50YXJhbQpwaWNvIGRlIG9ic2VydmHDp8O1ZXMgcHLDs3hpbW9zIGEgemVyby4KCk7Ds3MgdXNhbW9zIGNvbW8gbW9kZWxvIHBhcmEgZXN0ZSBmbHV4byBvcyBkYWRvcyBkYSBjdXRpYSAqRGFzeXByb2N0YQpjcm9jb25vdGEqIGNvbGV0YWRvcyBuYSBSZXNleCBUYXBhasOzcy1BcmFwaXVucyBlbnRyZSAyMDE0IGUgMjAyMSwgcGVsbwpncmFuZGUgbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBhcmEgdW1hIG1lc21hIFVDLiBPcyBkYWRvcyBkZSBkaXN0w6JuY2lhcyBwZXJwZW5kaWN1bGFyZXMgcGFyYSBlc3NhIGVzcMOpY2llIGFwcmVzZW50YW0gdHLDqnMgY2FyYWN0ZXLDrXN0aWNhcyBpbmRlc2VqYWRhczogbsO6bWVybyBleGNlc3Npdm8gZGUgcmVwZXRpw6fDtWVzIGFtb3N0cmFpcyBudW1hIG1lc21hIGVzdGHDp8OjbyBhbW9zdHJhbCwgcGljbyBkZSBkaXN0w6JuY2lhcyBwcsOzeGltbyBhIHplcm8gZSBlbXBpbGhhbWVudG8gZGUgb2JzZXJ2YcOnw7VlcyBlbSB1bWEgbWVzbWEgZGlzdMOibmNpYS4KClBhcmEgbGlkYXIgY29tIGFzIHJlcGV0acOnw7VlcywgdGVzdGFtb3MgYSBhbsOhbGlzZSBkb3MgZGFkb3MgY29tIHRvZGFzIGFzCnJlcGV0acOnw7VlcyBlIGNvbSBvIG7Dum1lcm8gZGUgcmVwZXRpw6fDtWVzIHJlZHV6aWRhcy4gUGFyYSBsaWRhciBjb20gb3MKcGljb3MgZGUgZGlzdMOibmNpYSBwcsOzeGltb3MgYSB6ZXJvLCB0ZXN0YW1vcyBvIHVzbyBkb3MgZGFkb3MgY29tIGRpc3TDom5jaWFzIGV4YXRhcyBlIGRpc3TDom5jaWFzIGFncnVwYWRhcy4gRXNzYXMgZXN0cmF0w6lnaWFzIGVzdMOjbyBkZXNjcml0YXMgbm9zIEZsdXhvcyAxLTMuIE5vIHByaW1laXJvIGZsdXhvLCBjb21lbnRhbW9zIHRhbWLDqW0gYXMgZXNjb2xoYXMgZmVpdGFzIGUgb3MgcmVzdWx0YWRvcyBvYnRpZG9zLiBPcyBkZW1haXMgZmx1eG9zIHPDo28gcmVwZXRpw6fDtWVzIGRlc3RlIHByaW1laXJvIGZsdXhvLCBwb3LDqW0gY29tIG11ZGFuw6dhIG5hIGVzdHJ1dHVyYSBkb3MgZGFkb3MuCgojIFJFVklTQVIgRVNTRSB0cmVjaG8gbm8gZmluYWwKCkVzcMOpY2llcyBjb20gbWFpb3IgbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzL1VDIHBvc3NpYmlsaXRhbSB0ZXN0YXIsIHBvc3Rlcmlvcm1lbnRlLCBlc3RyYXRpZmljYcOnw7VlcyBub3MgZGFkb3MsIHByZXNlcnZhbmRvIHVtIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBzYXRpc2ZhdMOzcmlvIGRlbnRybyBkb3MgZXN0cmF0b3MuIFBvciBpc3NvLCBjb21lw6dhbW9zIGFwcmVzZW50YW5kbyB1bSBmbHV4byBjb21wbGV0byBkZSBhbsOhbGlzZSwgaW5jbHVpbmRvICoqQW1vc3RyYWdlbSBwb3IgRGlzdMOibmNpYSBDb252ZW5jaW9uYWwqKiwgKipBbW9zdHJhZ2VtIHBvciBEaXN0w6JuY2lhIGNvbSBNw7psdGlwbGFzIENvdmFyacOhdmVpcyoqIGUgKipBbW9zdHJhZ2VtIHBvciBEaXN0w6JuY2lhIGNvbSBFc3RyYXRpZmljYcOnw6NvKiogbm9zIGRhZG9zIGNvbSBhcyBlc3DDqWNpZXMgY29tIG1haW9yIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7Vlcy4gUG9yIGlzc28sIHNlbGVjaW9uYW1vcyBjb21vIG1vZGVsbyBhIGVzcMOpY2llIGNvbSBvIG1haW9yIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwYXJhIHVtYSBtZXNtYSBVQyBlIGEgdGVyY2VpcmEgY29tIG8gbWFpb3IgbsO6bWVybyB0b3RhbCBkZSBvYnNlcnZhw6fDtWVzLgoKIyMgRXNww6ljaWUgTW9kZWxvIC0gKkRhc3lwcm9jdGEgY3JvY29ub3RhKiAtIFJlc2V4IFRhcGFqw7NzIEFyYXBpdW5zCgohW0ZvbnRlOiBiaW9saWIuY3pdKGh0dHBzOi8vd3d3LmJpb2xpYi5jei9JTUcvR0FML0JJRy8yMDU4NDkuanBnKQoKRXNzYSDDqSBhIGVzcMOpY2llIGNvbSBvIG1haW9yIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwYXJhIHVtYSBtZXNtYSBVQy4KQXByZXNlbnRvdSwgY29tbyBhIG1haW9yaWEgZGFzIGVzcMOpY2llcyBlbSBkaWZlcmVudGVzIFVDcywgdW0gcGljbyBkZQpvYnNlcnZhw6fDtWVzIHByw7N4aW1vIGEgZHNpdMOibmNpYSB6ZXJvLiBUYW1iw6ltIGFwcmVzZW50b3UgZWZlaXRvIGRlIGVtcGlsaGFtZW50byBzb2JyZSBhcyBkaXN0w6JuY2lhcyA1LCAxMCwgMTUgZSAyMG0sIGluZGljYW5kbyBxdWUgb3MgZGFkb3MgZm9yYW0gYXJyZW5kb25kYWRvcyBwYXJhIGVzc2FzIGRpc3TDom5jaWFzLgoKIyMjIE9idGVyIG9zIGRhZG9zIHBhcmEgYXMgYW7DoWxpc2VzCgrDiSBwb3Nzw612ZWwgb2J0ZXIgYXMgb2JzZXJ2YcOnw7VlcyBkYSBlc3DDqWNpZSBlIFVuaWRhZGUgZGUgQ29uc2VydmHDp8OjbyBkZSBpbnRlcmVzc2UgZSB0b3Juw6EtbGFzIGFuYWxpc8OhdmVpcyBwZWxvIHBhY290ZSBgRGlzdGFuY2VgIHV0aWxpemFuZG8gZHVhcyBmdW7Dp8O1ZXM6IGBmaWx0cmFyX2RhZG9zKClgIGUgYHRyYW5zZm9ybWFyX2RhZG9zX2Zvcm1hdG9fRGlzdGFuY2UoKWAuIEEgcHJpbWVpcmEgZmlsdHJhIGEgYmFzZSBkZSBkYWRvcyBvcmlnaW5hbCBhIHBhcnRpciBkYSBlc3DDqWNpZSBlIFVDIGRlc2VqYWRhIGVwbG9zIGFyZ3VtZW50b3MgYG5vbWVfc3BzYCBlIGBub21lX3Vjc2AsIGVucXVhbnRvIGEgc2VndW5kYSB0cmFuc2Zvcm1hIG9zIGRhZG9zIHBhcmEgbyBmb3JtYXRvIGRvIHBhY290ZSBgRGlzdGFuY2VgLgoKYGBge3J9CiMgY2FycmVnYXIgZGFkb3MKY3V0aWFfdGFwX2FyYXAgPC0gZmlsdHJhcl9kYWRvcygKICBub21lX3VjcyA9ICJyZXNleF90YXBham9zX2FyYXBpdW5zIiwKICBub21lX3NwcyA9ICJkYXN5cHJvY3RhX2Nyb2Nvbm90YSIKKSB8PiAKICB0cmFuc2Zvcm1hcl9kYWRvc19mb3JtYXRvX0Rpc3RhbmNlKCkKCmN1dGlhX3RhcF9hcmFwCmBgYAoKIyMjIEFtb3N0cmFnZW0gcG9yIERpc3TDom5jaWEgQ29udmVuY2lvbmFsCgojIyMjIEZsdXhvIDEgLSBEaXN0w6JuY2lhcyBleGF0YXMgY29tIHRvZGFzIGFzIHJlcGV0acOnw7VlcwoKIyMjIyMgUGxvdGFuZG8gbyBoaXN0b2dyYW1hIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2JzZXJ2YcOnw7VlcyBwZWxhIGRpc3TDom5jaWEKCk8gaGlzdG9ncmFtYSBpbnRlcmF0aXZvIGVzdMOhIGRpc3BvbsOtdmVsIG5vIGFwbGljYXRpdm8gZW0gU2hpbnkKYGFwcF9kaXN0YW5jaWFfaW50ZXJhdGl2by5SYCBlbSBgcGlwZXIzZF9tb25pdG9yYV9mbG9yZXN0YWxcYXBwc2AuCgpBIGRpc3RyaWJ1acOnw6NvIGRvcyBkYWRvcyBubyBoaXN0b2dyYW1hIHBlcm1pdGUgb2JzZXJ2YXIgdW0gcGljbyBkZQpvYnNlcnZhw6fDtWVzIHByw7N4aW1vIGEgemVybywgYXNzaW0gY29tbyBwaWNvcyBkZSBvYnNlcnZhw6fDo28gZW0gNSwgMTAsIDE1CmUgMjBtLCBhbMOpbSBkZSB1bWEgY29uc2lkZXLDoXZlbCBwZXJkYSBlbSBkZXRlY3RhYmlsaWRhZGUgYSBwYXJ0aXIgZG9zCjIwbS4gw4kgcG9zc8OtdmVsIGFsdGVyYXIgYSBiaW5hZ2VtIGRvcyBoaXN0b2dyYW1hcyBhdHJhdsOpcyBkbyBhcmd1bWVudG8KYGxhcmd1cmFfY2FpeGFgLiBOZXN0ZSBleGVtcGxvIGFqdXN0YW1vcyBwYXJhIDEsIG8gcXVlIGZhY2lsaXRhIGEKb2JzZXJ2YcOnw6NvIGRlIHBpY29zIGRlIGRldGVjYcOnw6NvIGUgZWZlaXRvcyBkZSAqaGVhcGluZyogbm9zIGRhZG9zLgoKYGBge3IsIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xMCwgd2FybmluZz1GQUxTRX0KY3V0aWFfdGFwX2FyYXAgfD4gCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IApwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKClBhcmEgZWxpbWluYXIgYXMgb2JzZXJ2YcOnw7VlcyBmZWl0YXMgYSBkaXN0w6JuY2lhcyBjb20gYmFpeGEKZGV0ZWN0YWJpbGlkYWRlLCB2YW1vcyB0ZXN0YXIgZGlmZXJlbnRlcyBwcm9wb3LDp8O1ZXMgZGUgdHJ1bmNhbWVudG8uCgojIyMjIyBUZXN0YW5kbyBkaXN0w6JuY2lhIGRlIHRydW5jYW1lbnRvICgqdyopCgpWYW1vcyBleHBsb3JhciBkaWZlcmVudGVzIGRpc3TDom5jaWFzIGRlIHRydW5jYW1lbnRvIHBhcmEgdW0gbWVzbW8gbW9kZWxvCmRlIGZ1bsOnw6NvIGNoYXZlIGNvbSBkaXN0cmlidWnDp8OjbyBoYWxmLW5vcm1hbC4gT3B0YW1vcyBwb3IgdHJ1bmNhciBvcwpkYWRvcyBwZWxhIHBlcmNlbnRhZ2VtIHBhcmEgcGFkcm9uaXphciBhIHJvdGluYSBwYXJhIGRpZmVyZW50ZXMKZXNww6ljaWVzLiBCdWNrbGFuZCBldCBhbC4gKDIwMDEpIHN1Z2VyZSB1bSBjb3J0ZSBlbnRyZSA1LTEwJSBkYXMKb2JzZXJ2YcOnw7VlcyBkZXRlY3RhZGFzIG5hcyBtYWlvcmVzIGRpc3TDom5jaWFzLiBWYW1vcyBzZWxlY2lvbmFyIG8gdmFsb3IKZGUgY29ydGUgcGVsbyBtb2RlbG8gY29tIG1lbGhvciBhanVzdGUgdXRpbGl6YW5kbyBhIGZ1bsOnw6NvIGBzZWxlY2lvbmFyX2Rpc3RhbmNpYV90cnVuY2FtZW50bygpYC4gUGFyYSBhdXRvbWF0aXphciBhIGF2YWxpYcOnw6NvIGRhCnRydW5jYWdlbSBwYXJhIHF1YWxxdWVyIGNvbmp1bnRvIGRlIGRhZG9zLCBpbXBsZW1lbnRhbW9zIG5vIGPDs2RpZ28gbwp0ZXN0ZSBwYXJhIGFzIHNlZ3VpbnRlcyBwcm9wb3LDp8O1ZXMgZGUgY29ydGU6IDUsIDEwLCAxNSwgMjAgZSAyNSUgZGFzCm9ic2VydmHDp8O1ZXMgbWFpcyBkaXN0YW50ZXMuIENvbnR1ZG8sIG9zIHZhbG9yZXMgZGUgY29ydGUgcG9kZW0gc2VyIGFsdGVyYWRvcyBwZWxvIHVzdcOhcmlvIGZvcm5lY2VuZG8gdW1hIGxpc3RhIGNvbSBub3ZvcyB2YWxvcmVzIGFvIGFyZ3VtZW50byBgZGlzdF90cnVuY2FtZW50b2AuIEEgZnVuw6fDo28gZ2VyYSB1bWEgdGFiZWxhIGNvbXBhcmFuZG8gb3MgbW9kZWxvcyBlCnRhbWLDqW0gcGxvdGFtb3Mgb3MgZ3LDoWZpY29zIGRvcyBtb2RlbG9zIGFqdXN0YWRvcyBwYXJhIG9zIGRhZG9zCnRydW5jYWRvcyB1c2FuZG8gYSBmdW7Dp8OjbyBwbG90YXJfLgoKIyMjIyMjIFRhYmVsYSBjb20gcmVzdW1vIGNvbXBhcmF0aXZvIGRvcyBtb2RlbG9zCgpgYGB7cn0KIyBjb25kdXogYSBzZWxlY2FvIGRhIG1lbGhvciBkaXN0YW5jaWEgZGUgdHJ1bmNhbWVudG8gYSBwYXJ0aXIgZG8gYWpzdXRlIGRlIG1vZGVsb3MgY29tIGZ1bmNhbyBkZSBkZXRlY2NhbyBoYWxmLW5vcm1hbCBzZW0gdGVybW9zIGRlIGFqdXN0ZQpjdXRpYV90YXBfYXJhcF9kaXN0X3RydW5jIDwtIGN1dGlhX3RhcF9hcmFwIHw+IAogIHNlbGVjaW9uYXJfZGlzdGFuY2lhX3RydW5jYW1lbnRvKCkKCmN1dGlhX3RhcF9hcmFwX2Rpc3RfdHJ1bmMkc2VsZWNhbwpgYGAKCk9zIGNyaXTDqXJpb3MgZGUgYWp1c3RlIGRvcyBtb2RlbG9zIHNlcnZlbSBhcXVpIGNvbW8gdW1hIGluZm9ybWHDp8Ojbwpjb21wbGVtZW50YXIsIG1hcyBuw6NvIHNlcsOjbyBkZWNpc2l2b3MgbmEgZXNjb2xoYSBkYSBkaXN0w6JuY2lhIGRlCnRydW5jYW1lbnRvLiBOYXR1cmFsbWVudGUsIGVsaW1pbmFuZG8gb3MgZGFkb3MgZGFzIGRpc3TDo25jaWFzIGRlIG1lbm9yCmRldGVjdGFiaWxpZGFkZSwgb3MgbW9kZWxvcyB0ZW5kZW0gYSB0ZXIgdW0gbWVsaG9yIGFqdXN0ZSBwZWxhIG1lbm9yCnZhcmlhYmlsaWRhZGUgZG9zIGRhZG9zLiBBbMOpbSBkaXNzbywgbmVzc2UgY2FzbyBvcyB2YWxvcmVzIGRlIGRlbHRhQUlDCnNlcsOjbyBzZW1wcmUgemVybywgcG9pcyBuw6NvIMOpIHBvc3PDrXZlbCBjb21wYXJhciB2YWxvcmVzIGRlIEFJQyBwYXJhCmNvbmp1bnRvcyBkZSBkYWRvcyBkaWZlcmVudGVzIChuZXNzZSBjYXNvIG9zIGRhZG9zIGRpZmVyZW0gZW0gbsO6bWVybyBkZQpvYnNlcnZhw6fDtWVzKS4KCiMjIyMjIyBQbG90YW5kbyBvIGhpc3RvZ3JhbWEgY29tIG9zIGRhZG9zIHRydW5jYWRvcy4KCkhpc3RvZ3JhbWFzIHJlc3VsdGFudGVzIGRvcyBtb2RlbG9zLCBjb20gdG9kYXMgYXMgZGlzdMOibmNpYXMgZGUKdHJ1bmNhZ2VtLCBwYXJhIGF1eGlsaWFyIG5hIHNlbGXDp8OjbyBkYSBtZWxob3IgZGlzdMOjbmNpYS4KCmBgYHtyfQpwbG90YXJfZnVuY2FvX2RldGVjY2FvX3NlbGVjYW9fZGlzdGFuY2lhX3RydW5jYW1lbnRvKGN1dGlhX3RhcF9hcmFwX2Rpc3RfdHJ1bmMpCmBgYAoKQXDDs3MgYXZhbGlhciB0YW50byBvIGFqdXN0ZSBkb3MgbW9kZWxvcyBxdWFudG8gb3MgZ3LDoWZpY29zLCBvcHRhbW9zIHBvcgp0cnVuY2FyIDEwJSBkYXMgb2JzZXJ2YcOnw7VlcyBmZWl0YXMgbmFzIG1haW9yZXMgZGlzdMOibmNpYXMuIEFwZXNhciBkb3MKbWVsaG9yZXMgdmFsb3JlcyBkZSBBSUMgZSBkZSBhanVzdGUgZG8gQ3JhbcOpci12b24gTWlzZXMgcGFyYSAyNSUsIG9zCmhpc3RvZ3JhbWFzIGNvbSBtb2RlbG9zIGFqdXN0YWRvcyBwYXJhIDI1JSwgMjAlIGUgMTUlIGFwcmVzZW50YXJhbQptb2RlbG9zIHF1YXNlIGxpbmVhcmVzIGUgY29tIHVtYSBncmFuZGUgcHJvYmFiaWxpZGFkZSBkZSBkZXRlw6fDo28gbm9zCsO6bHRpbW9zIGludGVydmFsb3MgZGUgZGlzdMOibmNpYS4gTyBtb2RlbG8gY29tIGNvcnRlIGRlIDEwJSBhcHJlc2VudG91CnVtYSBjdXJ2YSBkZWNyZXNjZW50ZSBlIG7Do28gdGVuZGV1IGEgemVybyBuYXMgw7psdGltYXMgZGlzdMOibmNpYXMuIErDoSBubwptb2RlbG9zIHBhcmEgNSUgYXMgZnVuw6fDtWVzIGRlIGRldGXDp8OjbyB0ZW5kZW0gYSB6ZXJvIG5vcyDDumx0aW1vcwppbnRlcnZhbG9zIGRlIGRpc3TDom5jaWEuIE8gY29ydGUgZGUgMTAlIGRhcyBvYnNlcnZhw6fDtWVzIG1haXMgZGlzdGFudGVzCnJlc3VsdG91IGVtIHVtYSBkaXN0w6JuY2lhIGRlIHRydW5jYW1lbnRvIGRlIDE1bS4KCiMjIyMjIEFqdXN0YW5kbyBkaWZlcmVudGVzIG1vZGVsb3MgZGUgZnVuw6fDtWVzIGRlIGRldGVjw6fDo28KCkFzIGZ1bsOnw7VlcyBkZSBkZXRlY8Onw6NvIHPDo28gYWp1c3RhZGFzIGF0cmF2w6lzIGRhIGZ1bsOnw6NvIGBkcygpYCBubyBwYWNvdGUKRGlzdGVuY2UgcGFyYSBvIFIuIFBhcmEgb3RpbWl6YXIgbyBmbHV4byBkZSBhanVzdGUgZGUgZGlmZXJlbnRlcyBtb2RlbG9zCmRlIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28sIGVtcGFjb3RhbW9zIGFzIGRpZmVyZW50ZXMgY29tYmluYcOnw7VlcyBkZSBmdW7Dp8O1ZXMKY2hhdmUgKHVuaWZvcm1lLCBoYWxmLW5vcm1hbCBlIGhhemFyZC1yYXRlKSBlIHRlcm1vcyBkZSBhanVzdGVzCihjb3NzZW5vLCBwb2xpbm9taWFsIHNpbXBsZXMgZSBwb2xpbm9taWFsIGRlIEhlcm1pdGUpIG5hIGZ1bsOnw6NvCmBhanVzdGFyX21vZGVsb3NfZGlzdGFuY2UoKWAuCgpQYXJhIGRlZmluaXIgYSBkaXN0w6JuY2lhIGRlIHRydW5jYW1lbnRvIGRvcyBkYWRvcyDDqSBuZWNlc3PDoXJpbyBmb3JuZWNlcgpvIGFyZ3VtZW50byBgdHJ1bmNhbWVudG9gLCBxdWUgcG9kZSBzZXIgZGVmaW5pZG8gdGFudG8gZW0gcGVyY2VudGFnZW0gZGUKY29ydGUgZG9zIGRhZG9zIHF1YW50byBlbSB2YWxvciBkZSBkaXN0w6NuY2lhLgoKIyMjIyMjIFVuaWZvcm1lIGNvbSB0ZXJtb3MgZGUgYWp1c3RlIENvc3Nlbm8gZSBwb2xpbm9taWFsIHNpbXBsZXMKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gdW5pZm9ybWUgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX3RhcF9hcmFwX3VuaWYgPC0gY3V0aWFfdGFwX2FyYXAgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gInVuaWYiLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIikKCmBgYAoKRGVudHJlIGFzIGNvbWJpbmHDp8O1ZXMgZGUgdGVybW9zIGRlIGFqdXN0ZXMgcGFyYSBhIGZ1bsOnw6NvIGNoYXZlIGRlCmRpc3RyaWJ1acOnw6NvIHVuaWZvcm1lLCBvIERpc3RhbmNlIHNlbGVjaW9ub3UgbyBtb2RlbG8gdW5pZm9ybWUgY29tCmFqdXN0ZSBwb2xpbm9taWFsIHNpbXBsZXMsIGNvbSBhcyBvcmRlbnMgMiwgNCBlIDYuIEVsZSBtYW50w6ltIGVzc2UKbW9kZWxvLCBlIGRlc2NhcnRhIG9zIGRlbWFpcy4gT3MgKldhcm5pbmdzKiBpbmRpY2FuZG8gcXVlIGEgZnVuw6fDo28gZGUKZGV0ZWPDp8OjbyBuw6NvIMOpIGVzdHJpdGFtZW50ZSBtb25vdMO0bmljYSBhdmlzYW0gcXVlIG9zIGRhZG9zIG7Do28gZm9yYW0KY29uc3RyYW5naWRvcyBwYXJhIGEgbW9ub3RvbmljaWRhZGUuIElzc28gcG9ycXVlIG8gdXNvIGRlIHRlcm1vcyBkZQphanVzdGVzLCBlc3BlY2lhbG1lbnRlIGRlIG9yZGVucyBhY2ltYSBkZSAyLCBwb2RlbSBsZXZhciDDoCBwZXJkYSBkYQptb25vdG9uaWRhZGUgKGEgY3VydmEgcG9kZSBzZSB0b3JuYXIgY3Jlc2NlbnRlIGVtIGFsZ3VtIG1vbWVudG8sIG8gcXVlCm7Do28gw6kgZGVzZWphZG8pLiDDiSBwcmVjaXNvIGF2YWxpYXIgc2UgYSBmYWx0YSBkZXNzZSBjb25zdHJhZ2ltZW50byBsZXZvdQplZmV0aXZhbWVudGUgw6AgcGVyZGEgZGEgbW9ub3RvbmljaWRhZGUgYW8gb2xoYXIgb3MgZ3LDoWZpY29zIGRlIGFqdXN0ZQpkb3MgbW9kZWxvcy4KCiMjIyMjIyBIYWxmLU5vcm1hbCBzZW0gdGVybW9zIGRlIGFqdXN0ZSBlIGNvbSB0ZXJtb3MgZGUgYWp1c3RlIENvc3Nlbm8gZSBQb2xpbm9taWFsIGRlIEhlcm1pdGUKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX3RhcF9hcmFwX2huIDwtIGN1dGlhX3RhcF9hcmFwIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCk5lc3RlIGNhc28sIG8gbW9kZWxvIHNlbGVjaW9uYWRvIHBlbG8gRGlzdGFuY2UgZm9pIG8gSGFsZi1ub3JtYWwgc2VtCm5lbmh1bSB0ZXJtbyBkZSBhanVzdGUuCgojIyMjIyMgSGF6YXJkLXJhdGUgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZSBDb3NzZW5vIGUgUG9saW5vbWlhbCBkZSBIZXJtaXRlCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhemFyZC1yYXRlIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYV90YXBfYXJhcF9ociA8LSBjdXRpYV90YXBfYXJhcCB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaHIiLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIikKYGBgCgpBcXVpIG8gbWVsaG9yIG1vZGVsbyBzZWxlY2lvbmFkbyBwZWxvIGBEaXN0YW5jZWAgZm9pIG8gSGF6YXJkLXJhdGUgc2VtIG9zCnRlcm1vcyBkZSBhanVzdGUuIE5lc3NlIGNhc28sIHRhbWLDqW0gaMOhIHVtICp3YXJuaW5nKiBwYXJhIG8gcHJvYmxlbWEgbmEKZGlzdHJpYnVpw6fDo28gZG9zIGRhZG9zLCBxdWUgYXByZXNlbnRhbSB1bSBwaWNvIHByw7N4aW1vIGEgZGlzdMOibmNpYSB6ZXJvCmUgbsOjbyBzw6NvIGJlbSBhanVzdGFkb3MgcGVsbyBtb2RlbG8gaGF6YXJkLWhhdGUuCgojIyMjIyBDb21wYXJhbmRvIG9zIG1vZGVsb3MKClBhcmEgY29tcGFyYXIgb3MgbW9kZWxvcyDDqSBwcmVjaXNvIGF2YWxpYXIgdHLDqnMgY3JpdMOpcmlvczogQUlDLCBhanVzdGUgZQpmb3JtYSBkYXMgZnVuw6fDtWVzIG5vcyBncsOhZmljb3MgZSBib25kYWRlIGRlIGFqdXN0ZS4gTyBwYWNvdGUgYERpc3RhbmNlYApwb3NzdWkgYSBmdW7Dp8OjbyBgc3VtbWFyaXplX2RzX21vZGVsc2AgcXVlIGdlcmEgdW1hIHRhYmVsYSBjb20gb3MgbW9kZWxvcwpwYXJhIGNvbXBhcmHDp8OjbyBkZSBhbGd1bnMgcGFyw6JtZXRyb3M6IGEgcHJpbWVpcmEgY29sdW5hICoqTW9kZWwqKiwKaW5kaWNhIGFzIGZ1bsOnw7VlcyBjaGF2ZXMgZSByZXNwZWN0aXZvcyB0ZXJtb3MgZGUgYWp1c3RlOyBhIGNvbHVuYQoqKkZvcm11bGEqKiBhcHJlc2VudGEgYXMgY292YXJpw6F2ZWlzLCBxdWFuZG8gaW5jbHXDrWRhcyBubyBtb2RlbG8sIG91Cn4gMSwgcXVhbmRvIG7Do28gaMOhIGNvdmFyacOhdmVpczsgKipDLXZNIHAtdmFsdWUqKiB2YWkgYXByZXNlbnRhciBvcwp2YWxvcmVzIGRlIHAgcGFyYSBvIHRlc3RlIGRlIGJvbmRhZGUgZGUgYWp1c3RlIGRlIENyYW3DqXItdm9uIE1pc2VzOwokXGhhdHtQX2F9JCBhcHJlc2VudGEgYSBwcm9iYWxpZGFkZSBkZSBkZXRlw6fDo28gZ2xvYmFsIGVzdGltYWRhIHBhcmEgY2FkYQptb2RlbG87ICoqc2UqKigkXGhhdHtQX2F9JCkgYXByZXNlbnRhIG8gZXJybyBwYWRyw6NvIHBhcmEgYXMgZXN0aW1hdGl2YXMKZGUgcHJvYmFiaWxpZGFkZSBkZSBkZXRlY8Onw6NvOyBlICRcRGVsdGEkQUlDIGFwcmVzZW50YSBvcyB2YWxvcmVzIGRlCmRpZmVyZW7Dp2EgZW50cmUgb3MgQUlDJ3MgZGUgbW9kZWxvcyBzdWJzZXF1ZW50ZXMuCgojIyMjIyMgVGFiZWxhIGNvbSBvIHJlc3VtbyBjb21wYXJhdGl2byBkb3MgbW9kZWxvcwoKYGBge3J9CmZsdXhvMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUgPC0gc2VsZWNpb25hcl9mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKAogIGN1dGlhX3RhcF9hcmFwX2huJGBTZW0gdGVybW9gLAogIGN1dGlhX3RhcF9hcmFwX2huJENvc3Nlbm8sCiAgY3V0aWFfdGFwX2FyYXBfaG4kYEhlcm1pdGUgcG9saW5vbWlhbGAsCiAgY3V0aWFfdGFwX2FyYXBfaHIkYFNlbSB0ZXJtb2AsCiAgY3V0aWFfdGFwX2FyYXBfaHIkQ29zc2VubywKICBjdXRpYV90YXBfYXJhcF9ociRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYV90YXBfYXJhcF91bmlmJENvc3Nlbm8sCiAgY3V0aWFfdGFwX2FyYXBfdW5pZiRgUG9saW5vbWlhbCBzaW1wbGVzYAopCgpmbHV4bzFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlCmBgYAoKRGVudHJlIG9zIG1vZGVsb3MgdGVzdGFkb3MsIG8gcXVlIGFwcmVzZW50b3UgbWVsaG9yIHZhbG9yIGRlIGFqdXN0ZSBlCkFJQyBmb2kgbyBoYXphcmQtcmF0ZS4gTyBhanVzdGUgZG8gQ3JhbcOpci12b24gTWlzZXMgZm9pIGNvbnNpZGVyYXZlbG1lbnRlIG1haW9yIHF1ZSBvcyBkZW1haXMgKHBhcmEgZXNzZSB0aXBvIGRlIHRlc3RlLCBxdWFudG8gbWFpb3IgbyB2YWxvciBkZSBwLCBtZWxob3IgbyBhanVzdGUpLCBhc3NpbSBjb21vIGFzIGRpZmVyZW7Dp2FzIG5vIGRlbHRhIEFJQyBmb3JhbSBiYXN0YW50ZSBlbGV2YWRhcy4KCiMjIyMjIyBHcsOhZmljb3MgZGUgYWp1c3RlIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZcOnw6NvIMOgcyBwcm9iYWJpbGlkYWRlcyBkZSBkZXRlw6fDo28KCmBgYHtyfQojIGdlcmFyIHVtYSBsaXN0YSBjb20gb3MgbW9kZWxvcyBzZWxlY2lvbmFkb3Mgb3JkZW5hZG9zIGRvIG1lbGhvciBwYXJhIG8gcGlvciBtb2RlbG8KZmx1eG8xX21vZGVsb3Nfc2VsZWNpb25hZG9zIDwtIGdlcmFyX2xpc3RhX21vZGVsb3Nfc2VsZWNpb25hZG9zKAogIGN1dGlhX3RhcF9hcmFwX2hyJGBTZW0gdGVybW9gLAogIGN1dGlhX3RhcF9hcmFwX3VuaWYkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2huJGBDb3NzZW5vYCwKICBjdXRpYV90YXBfYXJhcF91bmlmJGBQb2xpbm9taWFsIHNpbXBsZXNgLAogIGN1dGlhX3RhcF9hcmFwX2huJGBTZW0gdGVybW9gLCAKICBub21lX21vZGVsb3Nfc2VsZWNpb25hZG9zID0gZmx1eG8xX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZQopCgojIHBsb3RhciBhIHByb2JhYmlsaWRhZGUgZGUgZGV0ZWPDp8OjbyBvYnNlcnZhZGEgKGJhcnJhcykgZSBhIGVzcGVyYWRhIChsaW5oYXMgZSBwb250b3MpCnBsb3Rhcl9mdW5jYW9fZGV0ZWNjYW9fbW9kZWxvc19zZWxlY2lvbmFkb3MoZmx1eG8xX21vZGVsb3Nfc2VsZWNpb25hZG9zKQpgYGAKCk9saGFuZG8gcGFyYSBvcyBoaXN0b2dyYW1hcyBjb20gbW9kZWxvcyBhanVzdGFkb3MsIMOpIHBvc3PDrXZlbCBvYnNlcnZhciBvCmVmZWl0byBkbyBhY8O6bXVsbyBkZSBvYnNlcnZhw6fDtWVzIHByw7N4aW1vIGEgemVyby4gTyBtb2RlbG8gY29tIGEgZnVuw6fDo28KY2hhdmUgaGF6YXJkLWhhdGUgc2VtIHRlcm1vcyBkZSBhanVzdGUsIGFwZXNhciBkZSB0ZXIgYXByZXNlbnRhZG8gbwptZWxob3IgdmFsb3IgZGUgYWp1c3RlIHBlbG8gQ3JhbcOpci12b24gTWlzZXMgZSBvIG1lbGhvciB2YWxvciBkZSBBSUMsCmFwcmVzZW50b3UgZG9pcyBwcm9ibGVtYXMuIEFzIHByb2JhbGlkYWRlcyBkZSBkZXRlw6fDo28gZXN0aW1hZGFzIHBvcgppbnRldmFsbyBkZSBkaXN0w6JuY2lhIChiYXJyYXMgdmVyZGVzKSwgZmljYXJhbSBtdWl0byBiYWl4YXMuIEFsw6ltIGRpc3NvLAphIGN1cnZhIGRhIGZ1bsOnw6NvIGRlIGRldGXDp8OjbyBhcHJlc2VudGEgcGljbyBuYSBkaXN0w6JuY2lhIHByw7N4aW1hIGEgemVybywKZGVjYWluZG8gcmFwaWRhbWVudGUgZSBzZSBhcHJveGltYW5kbyBkZSB6ZXJvIGFvIGxvbmdvIGRvIGVpeG8gZGFzCmRpc3TDo25jaWFzLiBUb2RvcyBvcyBvdXRyb3MgcXVhdHJvIG1vZGVsb3MgdGl2ZXJhbSBhanVzdGUgZSBBSUMgYmFzdGFudGUKaW5mZXJpb3JlcyBhbyBoYXphcmQtaGF0ZS4gRW50cmV0YW50byBhcyBjdXJ2YXMgZXN0w6NvIHJlbGF0aXZhbWVudGUKbWVsaG9yZXMuIEFzIGN1cnZhcyBkbyBzZWd1bmRvIGUgdGVyY2Vpcm8gbW9kZWxvLCB1bmlmb3JtZSBjb20gYWp1c3RlCmNvc3Nlbm8gZSBoYWxmLW5vcm1hbCBjb20gYWp1c3RlIGNvc3Nlbm8sIHJlc3BlY3RpdmFtZW50ZSwgdGVuZGVtIMOgCnBlcmRhIGRlIG1vbm90b25pY2lkYWRlLiBBcyBkdWFzIMO6bHRpbWFzIGN1cnZhcywgcGFyYSBvcyBtb2RlbG9zCnVuaWZvcm1lIGNvbSBhanVzdGUgcG9saW5vbWlhbCBzaW1wbGVzIGUgaGFsZi1ub3JtYWwgc2VtIGFqdXN0ZSwgbsOjbwpwZXJkZW0gYSBtb25vdG9uaWNpZGFkZS4gRGUgZm9ybWEgZ2VyYWwsIGFzIHByb2JhYmlsaWRhZGVzIGRlIGRldGVjw6fDo28KbsOjbyB0w6ptIHVtIGJvbSBhanVzdGUgYWJhaXhvIGRhIGN1cnZhLCBlIG7Do28gYXByZXNlbnRhbSB1bSBkZWNhaW1lbnRvCmdyYWR1YWwgY29tIGEgZGlzdMOibmNpYS4gRXNzZXMgc8OjbyBwcm9ibGVtYXMgaW5lcmVudGVzIMOgIGRpc3RyaWJ1acOnw6NvCmRvcyBkYWRvcy4KCiMjIyMjIyBUZXN0ZSBkZSBib25kYWRlIGRlIGFqdXN0ZSBkb3MgbW9kZWxvcyBlIFEtUSBwbG90cwoKYGBge3J9CmJvbmRhZGVfYWp1c3RlX2ZsdXhvMSA8LSB0ZXN0YXJfYm9uZGFkZV9hanVzdGUoCiAgZmx1eG8xX21vZGVsb3Nfc2VsZWNpb25hZG9zLCAKICBwbG90ID0gVFJVRSwKICBjaGlzcSA9IFRSVUUsIAogIGludGVydmFsb3NfZGlzdGFuY2lhICA9ICBOVUxMCikKCmJvbmRhZGVfYWp1c3RlX2ZsdXhvMQpgYGAKCkFxdWkgc8OjbyBnZXJhZG9zIFEtUSBwbG90cyBxdWUgcGVybWl0ZW0gYXZhbGlhciBhIHF1YWxpZGFkZSBkbyBhanVzdGUKZG9zIG1vZGVsb3MuIEUgdGFtYsOpbSB1bWEgdGFiZWxhIGNvbSBvcyByZXN1bHRhZG9zIGRvIENhcm3DqXItdm9uIE1pc2VzLApvbmRlIFcgw6kgbyB2YWxvciBkbyB0ZXN0ZSBlIHAgc2V1IHZhbG9yIGRlIHNpZ25pZmljw6JuY2lhLiBOZXNzZSBjYXNvLApxdWFudG8gbWFpb3IgbyB2YWxvciBkZSBwLCBtZWxob3IgbyBhanVzdGUgZG8gbW9kZWxvLgoKIyMjIyMgQXZhbGlhbmRvIGFzIGVzdGltYXRpdmFzIGRlIEFidW5kw6JuY2lhIGUgRGVuc2lkYWRlCgpBcXVpLCBzw6NvIHJlc3VtaWRvcyBvcyBkYWRvcyBkZSB0YXhhIGRlIGVuY29udHJvLCBhYnVuZMOibmNpYSBlIGRlbnNpZGFkZQplbSB0csOqcyB0YWJlbGFzLgoKIyMjIyMjIENhcmFjdGVyw61zdGljYXMgZGEgw6FyZWEgZGUgZXN0dWRvIGUgZGEgdGF4YSBkZSBlbmNvbnRybwoKYGBge3J9CiMgZ2VyYSByZXN1bHRhZG9zIMOhcmVhIGRlIGVzdHVkbyBlIHRheGEgZGUgZW5jb250cm8KZmx1eG8xX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgZGFkb3MgPSBmbHV4bzFfbW9kZWxvc19zZWxlY2lvbmFkb3MsCiAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUsCiAgdGlwb19kZV9yZXN1bHRhZG8gPSAiYXJlYV9lc3R1ZG8iLCAKICBlc3RyYXRpZmljYWNhbyA9IEZBTFNFCikKCmZsdXhvMV9jYXJhY3RlcmlzdGljYXNfYXJlYV9lc3R1ZG9fdGF4YV9lbmNvbnRybwpgYGAKCiMjIyMjIyBDYXJhY3RlcsOtc3RpY2FzIGRlIGFidW5kw6JuY2lhLCBlc2ZvcsOnbyBlIGRldGVjw6fDo28KCmBgYHtyfQojIGdlcmFyIHJlc3VsdGFkb3MgYWJ1bmTDom5jaWEgZSBkZXRlY8Onw6NvCmZsdXhvMV9jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvIDwtIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgZGFkb3MgPSBmbHV4bzFfbW9kZWxvc19zZWxlY2lvbmFkb3MsCiAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUsCiAgdGlwb19kZV9yZXN1bHRhZG8gPSAiYWJ1bmRhbmNpYSIsIAogIGVzdHJhdGlmaWNhY2FvID0gRkFMU0UKKQoKZmx1eG8xX2NhcmFjdGVyaXN0aWNhc19lc2ZvcmNvX2FidW5kYW5jaWFfZGV0ZWNjYW8KYGBgCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkZSBkZW5zaWRhZGUKCmBgYHtyfQojIGdlcmFyIHJlc3VsdGFkb3MgZGVuc2lkYWRlIGUgY29lZmljaWVudGUgZGUgdmFyaWHDp8OjbwpmbHV4bzFfY2FyYWN0ZXJpc3RpY2FzX2RlbnNpZGFkZSA8LSBnZXJhcl9yZXN1bHRhZG9zX0Rpc3RhbmNlKAogIGRhZG9zID0gZmx1eG8xX21vZGVsb3Nfc2VsZWNpb25hZG9zLAogIHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImRlbnNpZGFkZSIsIAogIGVzdHJhdGlmaWNhY2FvID0gRkFMU0UKKQoKZmx1eG8xX2NhcmFjdGVyaXN0aWNhc19kZW5zaWRhZGUKYGBgCgojIyMjIEZsdXhvIDIgLSBEaXN0w6JuY2lhcyBleGF0YXMgc2VtIHJlcGV0acOnw7VlcwoKIyMjIyMgRmlsdHJhbmRvIG9zIGRhZG9zIHBhcmEgZWxpbWluYXIgYXMgcmVwZXRpw6fDtWVzCgpgYGB7cn0KY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhbyA8LSBmaWx0cmFyX2RhZG9zKAogIG5vbWVfdWNzID0gInJlc2V4X3RhcGFqb3NfYXJhcGl1bnMiLAogIG5vbWVfc3BzID0gImRhc3lwcm9jdGFfY3JvY29ub3RhIiwgCiAgdmFsaWRhY2FvX29icyA9ICJlc3BlY2llIgopIHw+IAogIHRyYW5zZm9ybWFyX2RhZG9zX2Zvcm1hdG9fRGlzdGFuY2UoYW1vc3RyYXNfcmVwZXRpZGFzID0gRkFMU0UpCgpjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvCmBgYAoKIyMjIyMgUGxvdGFuZG8gbyBoaXN0b2dyYW1hIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2JzZXJ2YcOnw7VlcyBwZWxhIGRpc3TDom5jaWEKCmBgYHtyLCBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9MTB9CmN1dGlhX3RhcF9hcmFwX3NlbV9yZXBldGljYW8gfD4gCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IApwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIFRlc3RhbmRvIGRpc3TDom5jaWEgZGUgdHJ1bmNhbWVudG8gKCp3KikKCiMjIyMjIyBUYWJlbGEgY29tIHJlc3VtbyBjb21wYXJhdGl2byBkb3MgbW9kZWxvcwoKYGBge3J9CiMgY29uZHV6IGEgc2VsZWNhbyBkYSBtZWxob3IgZGlzdGFuY2lhIGRlIHRydW5jYW1lbnRvIGEgcGFydGlyIGRvIGFqc3V0ZSBkZSBtb2RlbG9zIGNvbSBmdW5jYW8gZGUgZGV0ZWNjYW8gaGFsZi1ub3JtYWwgc2VtIHRlcm1vcyBkZSBhanVzdGUKY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19kaXN0X3RydW5jIDwtIGN1dGlhX3RhcF9hcmFwX3NlbV9yZXBldGljYW8gfD4gCiAgc2VsZWNpb25hcl9kaXN0YW5jaWFfdHJ1bmNhbWVudG8oKQoKY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19kaXN0X3RydW5jJHNlbGVjYW8KYGBgCgojIyMjIyMgUGxvdGFuZG8gbyBoaXN0b2dyYW1hIGNvbSBvcyBkYWRvcyB0cnVuY2Fkb3MuCgpgYGB7cn0KcGxvdGFyX2Z1bmNhb19kZXRlY2Nhb19zZWxlY2FvX2Rpc3RhbmNpYV90cnVuY2FtZW50byhjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvX2Rpc3RfdHJ1bmMpCgpgYGAKCiMjIyMjIEFqdXN0YW5kbyBkaWZlcmVudGVzIG1vZGVsb3MgZGUgZnVuw6fDtWVzIGRlIGRldGVjw6fDo28KCiMjIyMjIyBVbmlmb3JtZSArIENvc3Nlbm8KCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gdW5pZm9ybWUgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX3RhcF9hcmFwX3NlbV9yZXBldGljYW9fdW5pZiA8LSBjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJ1bmlmIiwgCiAgICB0ZXJtb3NfYWp1c3RlID0gImNvcyIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQoKYGBgCgojIyMjIyMgSGFsZi1Ob3JtYWwgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZQoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19obiA8LSBjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQoKYGBgCgojIyMjIyMgSGF6YXJkLXJhdGUgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZQoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYXphcmQtcmF0ZSBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19ociA8LSBjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJociIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQoKYGBgCgojIyMjIyBDb21wYXJhbmRvIG9zIG1vZGVsb3MKCiMjIyMjIyBUYWJlbGEgY29tIG8gcmVzdW1vIGNvbXBhcmF0aXZvIGRvcyBtb2RlbG9zCgpgYGB7cn0KZmx1eG8yX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zIDwtIGxpc3QoCiAgY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19obiwgCiAgY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19ociwgCiAgY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb191bmlmCikKCmZsdXhvMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUgPC0gc2VsZWNpb25hcl9mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKAogIGN1dGlhX3RhcF9hcmFwX3NlbV9yZXBldGljYW9faG4kYFNlbSB0ZXJtb2AsCiAgY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19obiRDb3NzZW5vLAogIGN1dGlhX3RhcF9hcmFwX3NlbV9yZXBldGljYW9faG4kYEhlcm1pdGUgcG9saW5vbWlhbGAsCiAgY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19ociRgU2VtIHRlcm1vYCwgCiAgY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19ociRDb3NzZW5vLCAKICBjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvX2hyJGBQb2xpbm9taWFsIHNpbXBsZXNgLAogIGN1dGlhX3RhcF9hcmFwX3NlbV9yZXBldGljYW9fdW5pZgopCgpmbHV4bzJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlCmBgYAoKIyMjIyMjIEdyw6FmaWNvcyBkZSBhanVzdGUgZGFzIGZ1bsOnw7VlcyBkZSBkZXRlY8Onw6NvIMOgcyBwcm9iYWJpbGlkYWRlcyBkZSBkZXRlY8Onw6NvCgpgYGB7cn0KIyBnZXJhciB1bWEgbGlzdGEgY29tIG9zIG1vZGVsb3Mgc2VsZWNpb25hZG9zIG9yZGVuYWRvcyBkbyBtZWxob3IgcGFyYSBvIHBpb3IgbW9kZWxvCmZsdXhvMl9tb2RlbG9zX3NlbGVjaW9uYWRvcyA8LSBnZXJhcl9saXN0YV9tb2RlbG9zX3NlbGVjaW9uYWRvcygKICBjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvX3VuaWYsCiAgY3V0aWFfdGFwX2FyYXBfc2VtX3JlcGV0aWNhb19obiRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9zZW1fcmVwZXRpY2FvX2hyJGBTZW0gdGVybW9gLAogIG5vbWVfbW9kZWxvc19zZWxlY2lvbmFkb3MgPSBmbHV4bzJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlCikKCiMgcGxvdGFyIGEgcHJvYmFiaWxpZGFkZSBkZSBkZXRlY8Onw6NvIG9ic2VydmFkYSAoYmFycmFzKSBlIGEgZXNwZXJhZGEgKGxpbmhhcyBlIHBvbnRvcykKcGxvdGFyX2Z1bmNhb19kZXRlY2Nhb19tb2RlbG9zX3NlbGVjaW9uYWRvcyhmbHV4bzJfbW9kZWxvc19zZWxlY2lvbmFkb3MpCmBgYAoKIyMjIyMjIFRlc3RlIGRlIGJvbmRhZGUgZGUgYWp1c3RlIGRvcyBtb2RlbG9zIGUgUS1RIHBsb3RzCgpgYGB7cn0KYm9uZGFkZV9hanVzdGVfZmx1eG8yIDwtIHRlc3Rhcl9ib25kYWRlX2FqdXN0ZSgKICBmbHV4bzJfbW9kZWxvc19zZWxlY2lvbmFkb3MsIAogIHBsb3QgPSBUUlVFLAogIGNoaXNxID0gVFJVRSwgCiAgaW50ZXJ2YWxvc19kaXN0YW5jaWEgID0gIE5VTEwKKQoKYm9uZGFkZV9hanVzdGVfZmx1eG8yCmBgYAoKIyMjIyMgQXZhbGlhbmRvIGFzIGVzdGltYXRpdmFzIGRlIEFidW5kw6JuY2lhIGUgRGVuc2lkYWRlCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkYSDDoXJlYSBkZSBlc3R1ZG8gZSBkYSB0YXhhIGRlIGVuY29udHJvCgpgYGB7cn0KIyBnZXJhIHJlc3VsdGFkb3Mgw6FyZWEgZGUgZXN0dWRvIGUgdGF4YSBkZSBlbmNvbnRybwpmbHV4bzJfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8gPC0gZ2VyYXJfcmVzdWx0YWRvc19EaXN0YW5jZSgKICBkYWRvcyA9IGZsdXhvMl9tb2RlbG9zX3NlbGVjaW9uYWRvcywKICByZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8yX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSwKICB0aXBvX2RlX3Jlc3VsdGFkbyA9ICJhcmVhX2VzdHVkbyIsIAogIGVzdHJhdGlmaWNhY2FvID0gRkFMU0UKKQoKZmx1eG8yX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvCmBgYAoKIyMjIyMjIENhcmFjdGVyw61zdGljYXMgZGUgYWJ1bmTDom5jaWEsIGVzZm9yw6dvIGUgZGV0ZWPDp8OjbwoKYGBge3J9CiMgZ2VyYSByZXN1bHRhZG9zIGFidW5kw6JuY2lhIGUgZGV0ZWPDp8OjbwpmbHV4bzJfY2FyYWN0ZXJpc3RpY2FzX2FidW5kYW5jaWEgPC0gZ2VyYXJfcmVzdWx0YWRvc19EaXN0YW5jZSgKICBkYWRvcyA9IGZsdXhvMl9tb2RlbG9zX3NlbGVjaW9uYWRvcywKICByZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8yX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSwKICB0aXBvX2RlX3Jlc3VsdGFkbyA9ICJhYnVuZGFuY2lhIiwgCiAgZXN0cmF0aWZpY2FjYW8gPSBGQUxTRQopCgpmbHV4bzJfY2FyYWN0ZXJpc3RpY2FzX2FidW5kYW5jaWEKYGBgCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkZSBkZW5zaWRhZGUKCmBgYHtyfQojIGdlcmEgcmVzdWx0YWRvcyBkZW5zaWRhZGUgZSBjb2VmaWNpZW50ZSBkZSB2YXJpYcOnw6NvCmZsdXhvMl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlIDwtIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgZGFkb3MgPSBmbHV4bzJfbW9kZWxvc19zZWxlY2lvbmFkb3MsCiAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUsCiAgdGlwb19kZV9yZXN1bHRhZG8gPSAiZGVuc2lkYWRlIiwgCiAgZXN0cmF0aWZpY2FjYW8gPSBGQUxTRQopCgpmbHV4bzJfY2FyYWN0ZXJpc3RpY2FzX2RlbnNpZGFkZQpgYGAKCiMjIyMgRmx1eG8gMyAtIERpc3TDom5jaWFzIGFncnVwYWRhcyBjb20gdG9kYXMgYXMgcmVwZXRpw6fDtWVzCgpBcXVpIHZhbW9zIHBhcnRpciBkbyBtZXNtbyBjb25qdW50byBkZSBkYWRvcyBkbyBGbHV4byAxCihgY3V0aWFfdGFwX2FyYXBgKSwgY29tIHRvZGFzIGFzIHJlcGV0acOnw7VlcywgbWFzIHZhbW9zIGFncnVwYXIgYXMKZGlzdMOibmNpYXMgZW0gaW50ZXJ2YWxvcy4gVmFtb3MgdXNhciBvIG1lc21vIHZhbG9yIGRlIHRydW5jYW1lbnRvLApyZW1vdmVuZG8gMTAlIGRhcyBvYnNlcnZhw6fDtWVzIG5hcyBtYWlvcmVzIGRpc3TDom5jaWFzLCBvIHF1ZSBzaWduaWZpY2EKcXVlIGFwcm92ZWl0YXJlbW9zIGFzIG9ic2VydmHDp8O1ZXMgZmVpdGFzIGF0w6kgMTVtIGRlIGRpc3TDom5jaWEgZG8Kb2JzZXJ2YWRvci4KCiMjIyMjIFBsb3RhbmRvIG8gaGlzdG9ncmFtYSBkYXMgZnJlcXXDqm5jaWFzIGRlIG9ic2VydmHDp8O1ZXMgcGVsYSBkaXN0w6JuY2lhCgpPIGhpc3RvZ3JhbWEgaW50ZXJhdGl2byBlc3TDoSBkaXNwb27DrXZlbCBubyBhcGxpY2F0aXZvIGVtIFNoaW55CmBhcHBfZGlzdGFuY2lhX2ludGVyYXRpdm8uUmBlbSBgcGlwZXIzZF9tb25pdG9yYV9mbG9yZXN0YWxcYXBwc2AuCgpBcXVpLCBwbG90YW1vcyBxdWF0cm8gaGlzdG9ncmFtYXMgY29tIGJpbmFnZW5zIGRpZmVyZW50ZXMsIHBhcmEgb2JzZXJ2YXIKbyBlZmVpdG8gZGUgYWdydXBhciBvcyBkYWRvcyBzb2JyZSBhcyBkaXN0cmlidWnDp8O1ZXMgZGFzIGZyZXF1w6puY2lhcyBkZQpvYnNlcnZhw6fDtWVzIG5vcyBoaXN0b2dyYW1hcy4KCmBgYHtyLCBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9MTB9CmN1dGlhX3RhcF9hcmFwIHw+IAogIHRpZHlyOjpkcm9wX25hKGRpc3RhbmNlKSB8PiAKcGxvdGFyX2Rpc3RyaWJ1aWNhb19kaXN0YW5jaWFfaW50ZXJhdGl2byhsYXJndXJhX2NhaXhhID0gMSkKCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xMH0KY3V0aWFfdGFwX2FyYXAgfD4gCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IApwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAyKQoKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0xNSwgZmlnLndpZHRoPTEwfQpjdXRpYV90YXBfYXJhcCB8PiAKICB0aWR5cjo6ZHJvcF9uYShkaXN0YW5jZSkgfD4gCnBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDMpCgpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9MTB9CmN1dGlhX3RhcF9hcmFwIHw+IAogIHRpZHlyOjpkcm9wX25hKGRpc3RhbmNlKSB8PiAKcGxvdGFyX2Rpc3RyaWJ1aWNhb19kaXN0YW5jaWFfaW50ZXJhdGl2byhsYXJndXJhX2NhaXhhID0gNSkKCmBgYAoKIyMjIyMgRGVmaW5pbmRvIG9zIGludGV2YWxvcyBkZSBkaXN0w6JuY2lhIGRlIGFncnVwYW1lbnRvCgrDiSBpbXBvcnRhbnRlIHJlc3NhbHRhciBxdWUgbyB2YWxvciBtw6F4aW1vIHBhcmEgY2F0ZWdvcml6YcOnw6NvIGRvcyBkYWRvcyBuw6NvIGRldmUgdXRsdHJhcGFzc2FyIG8gdmFsb3IgZGUgdHJ1bmNhZ2VtLiBDYXNvIGNvbnRyw6FyaW8sIG7Do28gc2Vyw6EgcG9zc8OtdmVsIGFqdXN0YXIgb3MgbW9kZWxvcyBhb3MgZGFkb3MuIAoKIyMjIyMjIFByaW1laXJhIGJpbmFnZW0gLSBJbnRlcnZhbG9zIGlndWFpcyBkZSAxLjVtCgpgYGB7cn0KY3V0aWFfdGFwX2FyYXBfYmluMSA8LSBjdXRpYV90YXBfYXJhcCB8PiAKICBkZWZpbmlyX2ludGVydmFsb3NfZGlzdGFuY2lhKAogICAgaW50ZXJ2YWxvc19kaXN0YW5jaWEgPSBzZXEoCiAgICAgIGZyb20gPSAwLAogICAgICB0byA9IDE1LAogICAgICBieSA9IDEuNQogICAgICApCiAgKQpgYGAKCiMjIyMjIyBTZWd1bmRhIGJpbmFnZW0gLSBQcmltZWlybyBpbnRlcnZhbG8gZGUgMW0gZSBkZW1haXMgaW50ZXJ2YWxvcyBkZSAxLjRtCgpgYGB7cn0KY3V0aWFfdGFwX2FyYXBfYmluMiA8LSBjdXRpYV90YXBfYXJhcCB8PiAKICBkZWZpbmlyX2ludGVydmFsb3NfZGlzdGFuY2lhKAogICAgaW50ZXJ2YWxvc19kaXN0YW5jaWEgPSBjKAogICAgICAwLAogICAgICBzZXEoCiAgICAgIGZyb20gPSAxLAogICAgICB0byA9IDE1LAogICAgICBieSA9IDEuNAogICAgICApCiAgICApCiAgKQogIApgYGAKCiMjIyMjIyBUZXJjZWlyYSBiaW5hZ2VtIC0gSW50ZXJ2YWxvcyBpZ3VhaXMgZGUgMi41bQoKYGBge3J9CmN1dGlhX3RhcF9hcmFwX2JpbjMgPC0gY3V0aWFfdGFwX2FyYXAgfD4gCiAgZGVmaW5pcl9pbnRlcnZhbG9zX2Rpc3RhbmNpYSgKICAgIGludGVydmFsb3NfZGlzdGFuY2lhID0gc2VxKAogICAgICBmcm9tID0gMCwKICAgICAgdG8gPSAxNSwKICAgICAgYnkgPSAyLjUKICAgICAgKQogICkKCmBgYAoKIyMjIyMgQWp1c3RhbmRvIGRpZmVyZW50ZXMgbW9kZWxvcyBkZSBmdW7Dp8O1ZXMgZGUgZGV0ZWPDp8OjbwoKIyMjIyMjIFVuaWZvcm1lICsgQ29zc2VubwoKUHJpbWVpcmEgQmluYWdlbQoKQXF1aSwgcG9yIGNvbnRhIGRhIGJpbmFnZW0sIG8gdHJ1bmNhbWVudG8gZGV2ZSBzZXIgZXhwcmVzc28gZW0gZGlzdMOibmNpYS4gUGFyYSBvcyBkYWRvcyBxdWUgZXN0YW1vcyB0cmFiYWxoYW5kbywgbyBjb3J0ZSBkZSAxMCUgZGFzIG9ic2VydmHDp8O1ZXMgbWFpcyBkaXN0YW50ZXMgdHJ1bmNhbSBvcyBkYWRvcyBlbSAxNW0uCgpgYGB7cn0KY3V0aWFfdGFwX2FyYXBfYmluMV91bmlmIDwtIGN1dGlhX3RhcF9hcmFwX2JpbjEgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gInVuaWYiLAogICAgdGVybW9zX2FqdXN0ZSA9ICJjb3MiLAogICAgdHJ1bmNhbWVudG8gPSAxNSkKCmBgYAoKU2VndW5kYSBiaW5hZ2VtCgpgYGB7cn0KCmN1dGlhX3RhcF9hcmFwX2JpbjJfdW5pZiA8LSBjdXRpYV90YXBfYXJhcF9iaW4yIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJ1bmlmIiwKICAgIHRlcm1vc19hanVzdGUgPSAiY29zIiwKICAgIHRydW5jYW1lbnRvID0gMTUpCgpgYGAKClRlcmNlaXJhIGJpbmFnZW0KCmBgYHtyfQoKY3V0aWFfdGFwX2FyYXBfYmluM191bmlmIDwtIGN1dGlhX3RhcF9hcmFwX2JpbjMgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gInVuaWYiLAogICAgdGVybW9zX2FqdXN0ZSA9ICJjb3MiLAogICAgdHJ1bmNhbWVudG8gPSAxNSkKCmBgYAoKIyMjIyMjIEhhbGYtTm9ybWFsIHNlbSB0ZXJtb3MgZGUgYWp1c3RlIGUgY29tIHRlcm1vcyBkZSBhanVzdGUKClByaW1laXJhIGJpbmFnZW0KCmBgYHtyfQoKY3V0aWFfdGFwX2FyYXBfYmluMV9obiA8LSBjdXRpYV90YXBfYXJhcF9iaW4xIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0cnVuY2FtZW50byA9IDE1KQoKYGBgCgpTZWd1bmRhIGJpbmFnZW0KCmBgYHtyfQoKY3V0aWFfdGFwX2FyYXBfYmluMl9obiA8LSBjdXRpYV90YXBfYXJhcF9iaW4yIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0cnVuY2FtZW50byA9IDE1KQoKYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KCmN1dGlhX3RhcF9hcmFwX2JpbjNfaG4gPC0gY3V0aWFfdGFwX2FyYXBfYmluMyB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaG4iLAogICAgdHJ1bmNhbWVudG8gPSAxNSkKCmBgYAoKIyMjIyMjIEhhemFyZC1yYXRlIHNlbSB0ZXJtb3MgZGUgYWp1c3RlIGUgY29tIHRlcm1vcyBkZSBhanVzdGUKClByaW1laXJhIGJpbmFnZW0KCmBgYHtyfQoKY3V0aWFfdGFwX2FyYXBfYmluMV9ociA8LSBjdXRpYV90YXBfYXJhcF9iaW4xIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJociIsCiAgICB0cnVuY2FtZW50byA9IDE1KQoKYGBgCgpTZWd1bmRhIGJpbmFnZW0KCmBgYHtyfQoKY3V0aWFfdGFwX2FyYXBfYmluMl9ociA8LSBjdXRpYV90YXBfYXJhcF9iaW4yIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJociIsCiAgICB0cnVuY2FtZW50byA9IDE1KQoKYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KCmN1dGlhX3RhcF9hcmFwX2JpbjNfaHIgPC0gY3V0aWFfdGFwX2FyYXBfYmluMyB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaHIiLAogICAgdHJ1bmNhbWVudG8gPSAxNSkKCmBgYAoKIyMjIyMgQ29tcGFyYW5kbyBvcyBtb2RlbG9zCgojIyMjIyMgVGFiZWxhIGNvbSBvIHJlc3VtbyBjb21wYXJhdGl2byBkb3MgbW9kZWxvcwoKYGBge3J9CmZsdXhvMy4xX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSA8LSBzZWxlY2lvbmFyX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUoCiAgY3V0aWFfdGFwX2FyYXBfYmluMV91bmlmLAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfaG4kYFNlbSB0ZXJtb2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluMV9obiRDb3NzZW5vLAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfaG4kYEhlcm1pdGUgcG9saW5vbWlhbGAsCiAgY3V0aWFfdGFwX2FyYXBfYmluMV9ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4xX2hyJENvc3Nlbm8sCiAgY3V0aWFfdGFwX2FyYXBfYmluMV9ociRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBkaXN0YW5jaWFfY2F0ZWdvcml6YWRhID0gVFJVRQopCgpmbHV4bzMuMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUKCmBgYAoKYGBge3J9CmZsdXhvMy4yX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSA8LSBzZWxlY2lvbmFyX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUoCiAgY3V0aWFfdGFwX2FyYXBfYmluMl91bmlmLAogIGN1dGlhX3RhcF9hcmFwX2JpbjJfaG4kYFNlbSB0ZXJtb2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluMl9obiRDb3NzZW5vLAogIGN1dGlhX3RhcF9hcmFwX2JpbjJfaG4kYEhlcm1pdGUgcG9saW5vbWlhbGAsCiAgY3V0aWFfdGFwX2FyYXBfYmluMl9ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4yX2hyJENvc3Nlbm8sCiAgY3V0aWFfdGFwX2FyYXBfYmluMl9ociRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBkaXN0YW5jaWFfY2F0ZWdvcml6YWRhID0gVFJVRQopCgpmbHV4bzMuMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUKYGBgCgpgYGB7cn0KZmx1eG8zLjNfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlIDwtIHNlbGVjaW9uYXJfZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSgKICBjdXRpYV90YXBfYXJhcF9iaW4zX3VuaWYsCiAgY3V0aWFfdGFwX2FyYXBfYmluM19obiRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4zX2huJENvc3Nlbm8sCiAgY3V0aWFfdGFwX2FyYXBfYmluM19obiRgSGVybWl0ZSBwb2xpbm9taWFsYCwKICBjdXRpYV90YXBfYXJhcF9iaW4zX2hyJGBTZW0gdGVybW9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaHIkQ29zc2VubywKICBjdXRpYV90YXBfYXJhcF9iaW4zX2hyJGBQb2xpbm9taWFsIHNpbXBsZXNgLAogIGRpc3RhbmNpYV9jYXRlZ29yaXphZGEgPSBUUlVFCikKCmZsdXhvMy4zX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZQpgYGAKCiMjIyMjIyBHcsOhZmljb3MgZGUgYWp1c3RlIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZWPDp8OjbyDDoHMgcHJvYmFiaWxpZGFkZXMgZGUgZGV0ZWPDp8OjbwoKUHJpbWVpcmEgYmluYWdlbQoKYGBge3J9CiMgR3LDoWZpY29zIGRlIGFqdXN0ZSBkYXMgZnVuw6fDtWVzIGRlIGRldGXDp8OjbyDDoHMgcHJvYmFiaWxpZGFkZXMgZGUgZGV0ZcOnw6NvCmZsdXhvMy4xX21vZGVsb3Nfc2VsZWNpb25hZG9zIDwtIGdlcmFyX2xpc3RhX21vZGVsb3Nfc2VsZWNpb25hZG9zKAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfaG4kYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfdW5pZiwKICBjdXRpYV90YXBfYXJhcF9iaW4xX2hyJGBTZW0gdGVybW9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfaG4kYFNlbSB0ZXJtb2AsIAogIG5vbWVfbW9kZWxvc19zZWxlY2lvbmFkb3MgPSBmbHV4bzMuMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUKKQoKIyBwbG90YXIgYSBwcm9iYWJpbGlkYWRlIGRlIGRldGVjw6fDo28gb2JzZXJ2YWRhIChiYXJyYXMpIGUgYSBlc3BlcmFkYSAobGluaGFzIGUgcG9udG9zKQpwbG90YXJfZnVuY2FvX2RldGVjY2FvX21vZGVsb3Nfc2VsZWNpb25hZG9zKAogIGZsdXhvMy4xX21vZGVsb3Nfc2VsZWNpb25hZG9zCikKYGBgCgpTZWd1bmRhIGJpbmFnZW0KCmBgYHtyfQojIEdyw6FmaWNvcyBkZSBhanVzdGUgZGFzIGZ1bsOnw7VlcyBkZSBkZXRlw6fDo28gw6BzIHByb2JhYmlsaWRhZGVzIGRlIGRldGXDp8OjbwpmbHV4bzMuMl9tb2RlbG9zX3NlbGVjaW9uYWRvcyA8LSBnZXJhcl9saXN0YV9tb2RlbG9zX3NlbGVjaW9uYWRvcygKICBjdXRpYV90YXBfYXJhcF9iaW4yX3VuaWYsCiAgY3V0aWFfdGFwX2FyYXBfYmluMl9ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4yX2huJGBDb3NzZW5vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4yX2huJGBTZW0gdGVybW9gLCAKICBub21lX21vZGVsb3Nfc2VsZWNpb25hZG9zID0gZmx1eG8zLjJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlCikKCiMgcGxvdGFyIGEgcHJvYmFiaWxpZGFkZSBkZSBkZXRlY8Onw6NvIG9ic2VydmFkYSAoYmFycmFzKSBlIGEgZXNwZXJhZGEgKGxpbmhhcyBlIHBvbnRvcykKcGxvdGFyX2Z1bmNhb19kZXRlY2Nhb19tb2RlbG9zX3NlbGVjaW9uYWRvcyhmbHV4bzMuMl9tb2RlbG9zX3NlbGVjaW9uYWRvcykKYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KIyBHcsOhZmljb3MgZGUgYWp1c3RlIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZcOnw6NvIMOgcyBwcm9iYWJpbGlkYWRlcyBkZSBkZXRlw6fDo28KZmx1eG8zLjNfbW9kZWxvc19zZWxlY2lvbmFkb3MgPC0gZ2VyYXJfbGlzdGFfbW9kZWxvc19zZWxlY2lvbmFkb3MoCiAgY3V0aWFfdGFwX2FyYXBfYmluM19obiRgQ29zc2Vub2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluM19ociRDb3NzZW5vLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaHIkYFBvbGlub21pYWwgc2ltcGxlc2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluM19ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4zX3VuaWYsCiAgY3V0aWFfdGFwX2FyYXBfYmluM19obiRgU2VtIHRlcm1vYCwgCiAgbm9tZV9tb2RlbG9zX3NlbGVjaW9uYWRvcyA9IGZsdXhvMy4zX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZQopCgojIHBsb3RhciBhIHByb2JhYmlsaWRhZGUgZGUgZGV0ZWPDp8OjbyBvYnNlcnZhZGEgKGJhcnJhcykgZSBhIGVzcGVyYWRhIChsaW5oYXMgZSBwb250b3MpCnBsb3Rhcl9mdW5jYW9fZGV0ZWNjYW9fbW9kZWxvc19zZWxlY2lvbmFkb3MoZmx1eG8zLjNfbW9kZWxvc19zZWxlY2lvbmFkb3MpCmBgYAoKIyMjIyMjIFRlc3RlIGRlIGJvbmRhZGUgZGUgYWp1c3RlIGRvcyBtb2RlbG9zIGUgUS1RIHBsb3RzCgoKUHJpbWVpcmEgYmluYWdlbQoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQpib25kYWRlX2FqdXN0ZV9mbHV4bzMuMSA8LSB0ZXN0YXJfYm9uZGFkZV9hanVzdGUoZmx1eG8zLjFfbW9kZWxvc19zZWxlY2lvbmFkb3MsCiAgcGxvdCA9IFRSVUUsCiAgY2hpc3EgPSBUUlVFLCAKICBpbnRlcnZhbG9zX2Rpc3RhbmNpYSA9ICBzZXEoCiAgICBmcm9tID0gMCwKICAgIHRvICA9IDE1LAogICAgYnkgPSAxLjUKICApCikKCmJvbmRhZGVfYWp1c3RlX2ZsdXhvMy4xCmBgYAoKU2VndW5kYSBiaW5hZ2VtCgpgYGB7cn0KYm9uZGFkZV9hanVzdGVfZmx1eG8zLjIgPC0gdGVzdGFyX2JvbmRhZGVfYWp1c3RlKGZsdXhvMy4yX21vZGVsb3Nfc2VsZWNpb25hZG9zLAogIHBsb3QgPSBUUlVFLAogIGNoaXNxID0gVFJVRSwgCiAgaW50ZXJ2YWxvc19kaXN0YW5jaWEgPSAgCiAgICBjKDAsIHNlcSgxLCAxNSwgMS40KSkKICApCgoKYm9uZGFkZV9hanVzdGVfZmx1eG8zLjIKYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KYm9uZGFkZV9hanVzdGVfZmx1eG8zLjMgPC0gdGVzdGFyX2JvbmRhZGVfYWp1c3RlKGZsdXhvMy4zX21vZGVsb3Nfc2VsZWNpb25hZG9zLAogIHBsb3QgPSBUUlVFLAogIGNoaXNxID0gVFJVRSwgCiAgaW50ZXJ2YWxvc19kaXN0YW5jaWEgPSAgc2VxKAogICAgZnJvbSA9IDAsCiAgICB0byAgPSAxNSwKICAgIGJ5ID0gMi41CiAgKQopCgpib25kYWRlX2FqdXN0ZV9mbHV4bzMuMwpgYGAKCiMjIyMjIEF2YWxpYW5kbyBhcyBlc3RpbWF0aXZhcyBkZSBBYnVuZMOibmNpYSBlIERlbnNpZGFkZQoKIyMjIyMjIENhcmFjdGVyw61zdGljYXMgZGEgw6FyZWEgZGUgZXN0dWRvIGUgZGEgdGF4YSBkZSBlbmNvbnRybwoKUHJpbWVpcmEgYmluYWdlbQoKYGBge3J9CiMgZ2VyYXIgcmVzdWx0YWRvcyBzb2JyZSBhIMOhcmVhLCBuw7ptZXJvIGRlIGRldGVjw6fDtWVzLCBlIHRheGEgZGUgZW5jb250cm8gIApmbHV4bzMuMV9jYXJhY3RlcmlzdGljYXNfYXJlYV9lc3R1ZG9fdGF4YV9lbmNvbnRybyA8LSBmbHV4bzMuMV9tb2RlbG9zX3NlbGVjaW9uYWRvcyB8PiAKICBnZXJhcl9yZXN1bHRhZG9zX0Rpc3RhbmNlKAogICAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMy4xX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSwKICAgIHRpcG9fZGVfcmVzdWx0YWRvID0gImFyZWFfZXN0dWRvIgogICkKCmZsdXhvMy4xX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvCmBgYAoKU2VndW5kYSBiaW5hZ2VtCgpgYGB7cn0KIyBnZXJhciByZXN1bHRhZG9zIHNvYnJlIGEgw6FyZWEsIG7Dum1lcm8gZGUgZGV0ZWPDp8O1ZXMsIGUgdGF4YSBkZSBlbmNvbnRybyAgCmZsdXhvMy4yX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGZsdXhvMy4yX21vZGVsb3Nfc2VsZWNpb25hZG9zIHw+IAogIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgICByZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlLAogICAgdGlwb19kZV9yZXN1bHRhZG8gPSAiYXJlYV9lc3R1ZG8iCiAgKQoKZmx1eG8zLjJfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8KYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KIyBnZXJhciByZXN1bHRhZG9zIHNvYnJlIGEgw6FyZWEsIG7Dum1lcm8gZGUgZGV0ZWPDp8O1ZXMsIGUgdGF4YSBkZSBlbmNvbnRybyAgCmZsdXhvMy4zX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGZsdXhvMy4zX21vZGVsb3Nfc2VsZWNpb25hZG9zIHw+IAogIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgICByZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjNfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlLAogICAgdGlwb19kZV9yZXN1bHRhZG8gPSAiYXJlYV9lc3R1ZG8iCiAgKQoKZmx1eG8zLjNfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8KYGBgCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkZSBhYnVuZMOibmNpYSwgZXNmb3LDp28gZSBkZXRlY8Onw6NvCgpQcmltZWlyYSBiaW5hZ2VtCgpgYGB7cn0KIyBnZXJhciByZXN1bHRhZG9zIHNvYnJlIGEgYWJ1bmTDom5jaWEKZmx1eG8zLjFfY2FyYWN0ZXJpc3RpY2FzX2FidW5kYW5jaWEgPC0gZmx1eG8zLjFfbW9kZWxvc19zZWxlY2lvbmFkb3MgfD4gCiAgZ2VyYXJfcmVzdWx0YWRvc19EaXN0YW5jZSgKICAgIHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzMuMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUsCiAgICB0aXBvX2RlX3Jlc3VsdGFkbyA9ICJhYnVuZGFuY2lhIgogICkKCmZsdXhvMy4xX2NhcmFjdGVyaXN0aWNhc19hYnVuZGFuY2lhCmBgYAoKU2VndW5kYSBiaW5hZ2VtCgpgYGB7cn0KIyBnZXJhciByZXN1bHRhZG9zIHNvYnJlIGEgYWJ1bmTDom5jaWEKZmx1eG8zLjJfY2FyYWN0ZXJpc3RpY2FzX2FidW5kYW5jaWEgPC0gZmx1eG8zLjJfbW9kZWxvc19zZWxlY2lvbmFkb3MgfD4gCiAgZ2VyYXJfcmVzdWx0YWRvc19EaXN0YW5jZSgKICAgIHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzMuMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUsCiAgICB0aXBvX2RlX3Jlc3VsdGFkbyA9ICJhYnVuZGFuY2lhIgogICkKCmZsdXhvMy4yX2NhcmFjdGVyaXN0aWNhc19hYnVuZGFuY2lhCmBgYAoKVGVyY2VpcmEgYmluYWdlbQoKYGBge3J9CiMgZ2VyYXIgcmVzdWx0YWRvcyBzb2JyZSBhIGFidW5kw6JuY2lhCmZsdXhvMy4zX2NhcmFjdGVyaXN0aWNhc19hYnVuZGFuY2lhIDwtIGZsdXhvMy4zX21vZGVsb3Nfc2VsZWNpb25hZG9zIHw+IAogIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgICByZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjNfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlLAogICAgdGlwb19kZV9yZXN1bHRhZG8gPSAiYWJ1bmRhbmNpYSIKICApCgpmbHV4bzMuM19jYXJhY3RlcmlzdGljYXNfYWJ1bmRhbmNpYQpgYGAKCiMjIyMjIyBDYXJhY3RlcsOtc3RpY2FzIGRlIGRlbnNpZGFkZQoKUHJpbWVpcmEgYmluYWdlbQoKYGBge3J9CiMgZ2VyYXIgcmVzdWx0YWRvcyBzb2JyZSBhIGRlbnNpZGFkZQpmbHV4bzMuMV9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlIDwtIGZsdXhvMy4xX21vZGVsb3Nfc2VsZWNpb25hZG9zIHw+IAogIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgICByZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlLAogICAgdGlwb19kZV9yZXN1bHRhZG8gPSAiZGVuc2lkYWRlIgogICkKCmZsdXhvMy4xX2NhcmFjdGVyaXN0aWNhc19kZW5zaWRhZGUKYGBgCgpTZWd1bmRhIGJpbmFnZW0KCmBgYHtyfQojIGdlcmFyIHJlc3VsdGFkb3Mgc29icmUgYSBkZW5zaWRhZGUKZmx1eG8zLjJfY2FyYWN0ZXJpc3RpY2FzX2RlbnNpZGFkZSA8LSBmbHV4bzMuMl9tb2RlbG9zX3NlbGVjaW9uYWRvcyB8PiAKICBnZXJhcl9yZXN1bHRhZG9zX0Rpc3RhbmNlKAogICAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMy4yX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSwKICAgIHRpcG9fZGVfcmVzdWx0YWRvID0gImRlbnNpZGFkZSIKICApCgpmbHV4bzMuMl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlCmBgYAoKVGVyY2VpcmEgYmluYWdlbQoKYGBge3J9CiMgZ2VyYXIgcmVzdWx0YWRvcyBzb2JyZSBhIGRlbnNpZGFkZQpmbHV4bzMuM19jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlIDwtIGZsdXhvMy4zX21vZGVsb3Nfc2VsZWNpb25hZG9zIHw+IAogIGdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgICByZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjNfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlLAogICAgdGlwb19kZV9yZXN1bHRhZG8gPSAiZGVuc2lkYWRlIgogICkKCmZsdXhvMy4zX2NhcmFjdGVyaXN0aWNhc19kZW5zaWRhZGUKYGBgCgojIyMgRmx1eG8gNCAtIEFtb3N0cmFnZW0gcG9yIERpc3TDom5jaWEgY29tIE3Dumx0aXBsYXMgQ292YXJpw6F2ZWlzCgpBcXVpIHZhbW9zIHVzYXIgYSBhYm9yZGFnZW0gZG8gRmx1eG8gMiwgc2VtIGFtb3N0cmFnZW5zIHJlcGV0aWRhcywgcGFyYQpvIGFqdXN0ZSBkZSBjb3ZhcmnDoXZlaXMuIFZhbW9zIHVzYXIgbyB0YW1hbmhvIGRvIGdydXBvIChzaXplKSBlIHRlbXBvIGRlIGRlbnNvIHBlcmNvcnJpZG8gYXTDqSBjYWRhIG9ic2VydmHDp8OjbyBjb21vIGV4ZW1wbG8gZGUgY292YXJpw6F2ZWlzLgoKIyMjIyBDYXJyZWdhbmRvIG9zIGRhZG9zCgpBcXVpIHZhbW9zIHRyYWJhbGhhciBjb20gb3MgZGFkb3MgZmlsdHJhZG9zLCBzZW0gcmVwZXRpw6fDtWVzLiBPIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyB0b3RhbCBmb2kgZGUgNTUuCgpgYGB7cn0KY3V0aWFzX2NvdiA8LSBmaWx0cmFyX2RhZG9zKAogIG5vbWVfdWNzID0gInJlc2V4X3RhcGFqb3NfYXJhcGl1bnMiLCAKICBub21lX3NwcyA9ICJkYXN5cHJvY3RhX2Nyb2Nvbm90YSIsCiAgdmFsaWRhY2FvX29icyA9ICJlc3BlY2llIgopCgpjdXRpYXNfY292X2Rpc3RhbmNlIDwtIHRyYW5zZm9ybWFyX2RhZG9zX2Zvcm1hdG9fRGlzdGFuY2UoCiAgY3V0aWFzX2NvdiwKICBhbW9zdHJhc19yZXBldGlkYXMgPSBGQUxTRSkKCmN1dGlhc19jb3ZfZGlzdGFuY2UKYGBgCgojIyMjIFBsb3RhbmRvIG8gaGlzdG9ncmFtYQoKYGBge3J9CmN1dGlhc19jb3ZfZGlzdGFuY2UgfD4gCnBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDEpCgpgYGAKCiMjIyMgQWp1c3RhbmRvIGRpZmVyZW50ZXMgbW9kZWxvcyBjb20gY292YXJpw6F2ZWlzCgpQYXJhIG8gdXNvIGRlIGNvdmVyacOhdmVpcywgcG9kZW1vcyB1c2FyIHNvbWVudGUgYXMgZGlzdHJpYnVpw6fDtWVzCmhhbGYtbm9ybWFsIG91IGhhemFyZC1yYXRlLCBwb2lzIGFtYmFzIHBvc3N1ZW0gbyBwYXLDom1ldHJvIGVzY2FsYXIgKHNpZ21hKSBwZWxvCnF1YWwgbyB2ZXRvciBkYXMgY292YXJpw6F2ZWlzIHNlcsOhIG11bHRpcGxpY2Fkby4gTsOjbyDDqSByZWNvbWVuZMOhdmVsIG8gdXNvCmRlIHRlcm1vcyBkZSBhanVzdGUgY29tIG8gdXNvIGRlIGNvdmFyacOhdmVpcyBwZWxhIGdyYW5kZSBjaGFuY2UgZGUgcGVyZGEKZGUgbW9ub3RvbmljaWRhZGUgbmFzIGN1cnZhcyBkYXMgZnVuw6fDtWVzIGRlIGRldGVjw6fDo28uIEFzc2ltLCB2YW1vcwp0cmFiYWxoYXIgY29tIGFzIHNlZ3VpbnRlcyBjb21iaW5hw6fDtWVzIGRlIG1vZGVsb3MuCgojIyMjIyBIYWxmLW5vcm1hbCBzZW0gdGVybW9zIGRlIGFqdXN0ZSAoSE4pCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhbGYtbm9ybWFsLCBzZW0gY292YXJpw6F2ZWwsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYXNfY292X2Rpc3RhbmNlX2huIDwtIGN1dGlhc19jb3ZfZGlzdGFuY2UgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhuIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIKICAgICkKCmN1dGlhc19jb3ZfZGlzdGFuY2VfaG4kYFNlbSB0ZXJtb2AKYGBgCgojIyMjIyBITiArIFRhbWFuaG8gZG8gZ3J1cG8gKEhOICsgUykKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwsIGNvbSB0YW1hbmhvIGRvIGdydXBvIGNvbW8gY292YXJpw6F2ZWwsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYXNfY292X2Rpc3RhbmNlX2huX3NpemUgPC0gY3V0aWFzX2Nvdl9kaXN0YW5jZSB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaG4iLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIiwKICAgIGZvcm11bGEgPSB+IHNpemUKICAgICkKCmN1dGlhc19jb3ZfZGlzdGFuY2VfaG5fc2l6ZQpgYGAKCiMjIyMjIEhOICsgVGFtYW5obyBkbyBncnVwbyAoSE4gKyBTKQoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCwgY29tIHRhbWFuaG8gZG8gZ3J1cG8gY29tbyBjb3ZhcmnDoXZlbCwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhc19jb3ZfZGlzdGFuY2VfaG5fc2l6ZV90aW1lIDwtIGN1dGlhc19jb3ZfZGlzdGFuY2UgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhuIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIsCiAgICBmb3JtdWxhID0gfiBzaXplICsgY2Vuc2VfdGltZQogICAgKQoKY3V0aWFzX2Nvdl9kaXN0YW5jZV9obl9zaXplX3RpbWUKYGBgCgojIyMjIyBIYXphcmQtcmF0ZSBzZW0gdGVybW9zIGRlIGFqdXN0ZSAoSFopCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhemFyZC1yYXRlLCBzZW0gY292YXJpw6F2ZWwsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYXNfY292X2Rpc3RhbmNlX2hyIDwtIGN1dGlhc19jb3ZfZGlzdGFuY2UgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhyIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIKICAgICkKCmN1dGlhc19jb3ZfZGlzdGFuY2VfaHIkYFNlbSB0ZXJtb2AKYGBgCgojIyMjIyMgSFogKyBUYW1hbmhvIGRvIGdydXBvIChIWiArIFMpCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhemFyZC1yYXRlLCBjb20gdGFtYW5obyBkbyBncnVwbyBjb21vIGNvdmFyacOhdmVsLCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2Nvdl9kaXN0YW5jZV9ocl9zaXplIDwtIGN1dGlhc19jb3ZfZGlzdGFuY2UgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhyIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIsCiAgICBmb3JtdWxhID0gfiBzaXplCiAgICApCgpjdXRpYXNfY292X2Rpc3RhbmNlX2hyX3NpemUKYGBgCgojIyMjIyMgSFogKyBUYW1hbmhvIGRvIGdydXBvIChIWiArIFMpCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhemFyZC1yYXRlLCBjb20gdGFtYW5obyBkbyBncnVwbyBjb21vIGNvdmFyacOhdmVsLCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2Nvdl9kaXN0YW5jZV9ocl9zaXplX3RpbWUgPC0gY3V0aWFzX2Nvdl9kaXN0YW5jZSB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaHIiLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIiwKICAgIGZvcm11bGEgPSB+IHNpemUgKyBjZW5zZV90aW1lCiAgICApCgpjdXRpYXNfY292X2Rpc3RhbmNlX2hyX3NpemVfdGltZQpgYGAKCiMjIyMjIENvbXBhcmFuZG8gb3MgbW9kZWxvcwoKIyMjIyMjIFRhYmVsYSBjb20gbyByZXN1bW8gY29tcGFyYXRpdm8gZG9zIG1vZGVsb3MKCkFxdWksIHZhbW9zIHNlbGVjaW9uYXIgc29tZW50ZSBvcyBtb2RlbG9zIHNlbSB0ZXJtb3MgZGUgYWp1c3RlLCBjb20gZSBzZW0gY292YXJpw6F2ZWlzLgoKYGBge3J9CmN1dGlhc19jb3ZfZGlzdGFuY2VfbWVsaG9yX21vZGVsbyA8LSAKICBzZWxlY2lvbmFyX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUoCiAgY3V0aWFzX2Nvdl9kaXN0YW5jZV9obiRgU2VtIHRlcm1vYCwKICBjdXRpYXNfY292X2Rpc3RhbmNlX2huX3NpemUsCiAgY3V0aWFzX2Nvdl9kaXN0YW5jZV9obl9zaXplX3RpbWUsCiAgY3V0aWFzX2Nvdl9kaXN0YW5jZV9ociRgU2VtIHRlcm1vYCwKICBjdXRpYXNfY292X2Rpc3RhbmNlX2hyX3NpemUsCiAgY3V0aWFzX2Nvdl9kaXN0YW5jZV9ocl9zaXplX3RpbWUKKQoKY3V0aWFzX2Nvdl9kaXN0YW5jZV9tZWxob3JfbW9kZWxvCgpgYGAKCk9ic2VydmUgcXVlIG5lc3NlIGNhc28gYXMgY292YXJpw6F2aWVzIGFsdGVyYXJhbSBwb3VjbyBvIGFqdXN0ZSBkb3MgbW9kZWxvcy4KCiMjIyMjIyBHcsOhZmljb3MgZGUgYWp1c3RlIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZcOnw6NvIMOgcyBwcm9iYWJpbGlkYWRlcyBkZSBkZXRlw6fDo28KCkFpbmRhIGVzdGFtb3MgYWp1c3RhbmRvIGEgZnVuw6fDo28gcGFyYSBwb2RlciBnZXJhciBvcyBncsOhZmljb3MgZG9zCm1vZGVsb3MgY29tIGNvdmFyacOhdmVpcy4gQSBmdW7Dp8OjbyBjcmlhZGEgcGFyYSBvcyBncsOhZmljb3MgYWluZGEgbsOjbwpjb21wb3J0YSBvcyBkYWRvcyBkZSBtb2RlbG9zIGNvbSBjb3ZhcmnDoXZlaXMuCgpgYGB7cn0KbW9kZWxvc19jdXRpYXNfY292X2Rpc3RhbmNlIDwtCiAgZ2VyYXJfbGlzdGFfbW9kZWxvc19zZWxlY2lvbmFkb3MoCiAgICBjdXRpYXNfY292X2Rpc3RhbmNlX2hyX3NpemVfdGltZSwKICAgIGN1dGlhc19jb3ZfZGlzdGFuY2VfaG5fc2l6ZV90aW1lLAogICAgY3V0aWFzX2Nvdl9kaXN0YW5jZV9obiRgU2VtIHRlcm1vYCwKICAgIGN1dGlhc19jb3ZfZGlzdGFuY2VfaG5fc2l6ZSwKICAgIGN1dGlhc19jb3ZfZGlzdGFuY2VfaHJfc2l6ZSwKICAgIGN1dGlhc19jb3ZfZGlzdGFuY2VfaHIkYFNlbSB0ZXJtb2AsCiAgICBub21lX21vZGVsb3Nfc2VsZWNpb25hZG9zID0gY3V0aWFzX2Nvdl9kaXN0YW5jZV9tZWxob3JfbW9kZWxvCiAgKQoKcGxvdGFyX2Z1bmNhb19kZXRlY2Nhb19tb2RlbG9zX3NlbGVjaW9uYWRvcyhtb2RlbG9zX2N1dGlhc19jb3ZfZGlzdGFuY2UpCgpgYGAKCiMjIyMjIyBUZXN0ZSBkZSBib25kYWRlIGRlIGFqdXN0ZSBkb3MgbW9kZWxvcyBlIFEtUSBwbG90cwoKQWluZGEgZXN0YW1vcyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBwYXJhIHBvZGVyIGdlcmFyIGEgdGFiZWxhIGNvbSBvcwpyZXN1bHRhZG9zIGRvIENyYW3DqXItdm9uIE1pc2VzIGUgb3MgZ3LDoWZpY29zIGRvcyBtb2RlbG9zIGNvbQpjb3ZhcmnDoXZlaXMuIEEgZnVuw6fDo28gY3JpYWRhIHBhcmEgZ2VyYXIgdGFiZWxhIGUgb3MgUS1RIHBsb3RzIGFpbmRhIG7Do28KY29tcG9ydGEgb3MgZGFkb3MgZGUgbW9kZWxvcyBjb20gY292YXJpw6F2ZWlzLgoKYGBge3J9CnRlc3Rhcl9ib25kYWRlX2FqdXN0ZSgKICBtb2RlbG9zX2N1dGlhc19jb3ZfZGlzdGFuY2UsCiAgcGxvdCA9IFRSVUUsCiAgbmJvb3QgPSAxMDAKKQoKYGBgCgojIyMjIyBBdmFsaWFuZG8gYXMgZXN0aW1hdGl2YXMgZGUgQWJ1bmTDom5jaWEgZSBEZW5zaWRhZGUKClBhcmEgbyB1c28gZGUgY292YXJpw6F2ZWlzLCBhcyBlc3RpbWF0aXZhcyBkZSBhYnVuZMOibmNpYS9kZW5zaWRhZGUgZGV2ZW0Kc2VyIGZlaXRhcyBhdHJhdsOpcyBkbyBib290c3RyYXAgKGZ1bsOnw6NvIGBib290ZGh0YCBkbyBEaXN0YW5jZSkuIEFpbmRhCmVzdGFtb3MgaW1wbGVtZW50YW5kbyBvIGJvb3RzdHJhcCBlbSBub3NzbyBmbHV4byBkZSBlc3RpbWF0aXZhcyBkZSB0YXhhCmRlIGVuY29udHJvLCBhYnVuZMOibmNpYSBlIGRlbnNpZGFkZS4KCiMjIyMjIyAqKsOBcmVhIGNvYmVydGEgcGVsYSBBbW9zdHJhZ2VtKioKCmBgYHtyfQoKZ2VyYXJfcmVzdWx0YWRvc19EaXN0YW5jZSgKICBtb2RlbG9zX2N1dGlhc19jb3ZfZGlzdGFuY2UsCiAgY3V0aWFzX2Nvdl9kaXN0YW5jZV9tZWxob3JfbW9kZWxvLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImFyZWFfZXN0dWRvIgogICkKCmBgYAoKIyMjIyMjICoqw4FidW5kw6JuY2lhKioKCmBgYHtyfQoKZ2VyYXJfcmVzdWx0YWRvc19EaXN0YW5jZSgKICBtb2RlbG9zX2N1dGlhc19jb3ZfZGlzdGFuY2UsCiAgY3V0aWFzX2Nvdl9kaXN0YW5jZV9tZWxob3JfbW9kZWxvLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImFidW5kYW5jaWEiCiAgKQoKYGBgCgojIyMjIyMgKipEZW5zaWRhZGUqKgoKYGBge3J9CgpnZXJhcl9yZXN1bHRhZG9zX0Rpc3RhbmNlKAogIG1vZGVsb3NfY3V0aWFzX2Nvdl9kaXN0YW5jZSwKICBjdXRpYXNfY292X2Rpc3RhbmNlX21lbGhvcl9tb2RlbG8sCiAgdGlwb19kZV9yZXN1bHRhZG8gPSAiZGVuc2lkYWRlIgogICkKCmBgYAoKIyMjIEZsdXhvIDUgLSBBbW9zdHJhZ2VtIHBvciBkaXN0w6JuY2lhIGNvbSBlc3RyYXRpZmljYcOnw6NvIHBvciBVbmlkYWRlIGRlIENvbnNlcnZhw6fDo28KCkEgZXN0cmF0aWZpY2HDp8OjbyBkb3MgZGFkb3MgYSBwYXJ0aXIgZG8gcGFjb3RlIERpc3RhbmNlIHBhcmEgbyBSIHPDsyDDqSBwb3Nzw612ZWwgYXRyYXbDqXMgZGEgdmFyacOhdmVsIGBSZWdpb24uTGFiZWxgLiBBc3NpbSwgYXByZXNlbnRhbW9zIHVtIGZsdXhvIGRlIGVzdHJhdGlmaWNhw6fDo28gdXRpbGl6YW5kbyBhaW5kYSBvcyBkYWRvcyBkYSBjdXRpYSwgKkRhc3lwcm9jdGEgY3JvY29ub3RhKiwgcGFyYSBtYWlzIGRlIHVtYSB1bmlkYWRlIGRlIGNvbnNlcnZhw6fDo28uIAoKIyMjIyBFeHBsb3JhbmRvIG9zIGRhZG9zIGRlbnRybyBkZSBjYWRhIGVzdHJhdG8gZXNwYWNpYWw6CgpOYSBQQVJURSBJViAtIEV4cGxvcmFuZG8gZSBzZWxlY2lvbmFuZG8gb3MgZGFkb3MgcGFyYSBhcyBhbsOhbGlzZXMsIGZpbHRyYW1vcyBvcyBkYWRvcyBkZSAqRGFzeXByb2N0YSBjcm9jb25vdGEqLiBBIGVzcMOpY2llIGZvaSBvYnNlcnZhZGEgZW0gcXVhdHJvIFVuaWRhZGVzIGRlIENvbnNlcnZhw6fDo28sIGNvbSBvcyByZXNwZWN0aXZvcyBuw7ptZXJvcyBkZSBvY29ycsOqbmNpYTogUmVzZXggVGFwYWrDs3MtQXJhcGl1bnMgKG4gPSAxMzk1KSwgUGFybmEgZGEgU2VycmEgZG8gUGFyZG8gKG4gPSAyNTcpLCBFc2VjIGRhIFRlcnJhIGRvIE1laW8gKG4gPSAyMzUpLCBlIFJlc2V4IFJpb3ppbmhvIGRvIEFuZnLDrXNpbyAobiA9IDIyNSkuIEVtIHRvZGFzIGFzIFVDcyBvIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyDDqSBhbHRvLCBkZSBtb2RvIHF1ZSBpbmNsdcOtbW9zIHRvZGFzIGFzIFVDcyBuYSBhbsOhbGlzZSBkZSBkYWRvcy4gCgojIyMgQ2FycmVnYXIgRGFkb3MKCmBgYHtyfQojIGZpbHRyYXIgZGFkb3MgZGFzIGN1dGlhcyBwYXJhIGFzIHF1YXRybyBVQ1Mgb25kZSBvY29ycmU6CmN1dGlhcyA8LSBmaWx0cmFyX2RhZG9zKAogIG5vbWVfdWNzID0gYygKICAgICJyZXNleF90YXBham9zX2FyYXBpdW5zIiwgCiAgICAicGFybmFfZGFfc2VycmFfZG9fcGFyZG8iLAogICAgImVzZWNfZGFfdGVycmFfZG9fbWVpbyIsIAogICAgInJlc2V4X3Jpb3ppbmhvX2RvX2FuZnJpc2lvIgogICksCiAgbm9tZV9zcHMgPSAiZGFzeXByb2N0YV9jcm9jb25vdGEiLAogIHZhbGlkYWNhb19vYnMgPSAiZXNwZWNpZSIKKQoKY3V0aWFzX2Rpc3RhbmNlIDwtIHRyYW5zZm9ybWFyX2RhZG9zX2Zvcm1hdG9fRGlzdGFuY2UoCiAgY3V0aWFzLAogIGFtb3N0cmFzX3JlcGV0aWRhcyA9IFRSVUUpCgpjdXRpYXNfZGlzdGFuY2UKYGBgCgoKIyMjIyMgUGxvdGFuZG8gbyBoaXN0b2dyYW1hIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2NvcnLDqm5jaWEgcGVsYSBkaXN0w6JuY2lhCiMjIyMjIyBEYWRvcyBHbG9iYWlzCgpQbG90YW5kbyBvIGhpc3RvZ3JhbWEgcGFyYSBvcyBkYWRvcyBnbG9iYWlzLgoKYGBge3J9CmN1dGlhc19kaXN0YW5jZSB8PiAKICB0aWR5cjo6ZHJvcF9uYShkaXN0YW5jZSkgfD4gCnBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDEpCmBgYAoKIyMjIyMjIFBvciBFc3RyYXRvCgpQbG90YW5kbyBvIGhpc3RvZ3JhbWEgcGFyYSBjYWRhIHVtYSBkYXMgVUNTCgojIyMjIyMjICoqUmVzZXggVGFwYWrDs3MtQXJhcGl1bnMqKgoKYGBge3J9CmN1dGlhc190YXBfZGlzdGFuY2UgPC0gZmlsdHJhcl9kYWRvcygKICBub21lX3VjcyA9ICJyZXNleF90YXBham9zX2FyYXBpdW5zIiwKICBub21lX3NwcyA9ICJkYXN5cHJvY3RhX2Nyb2Nvbm90YSIsCiAgdmFsaWRhY2FvX29icyA9ICJlc3BlY2llIgopIHw+IAogIHRyYW5zZm9ybWFyX2RhZG9zX2Zvcm1hdG9fRGlzdGFuY2UoYW1vc3RyYXNfcmVwZXRpZGFzID0gVFJVRSkKCmN1dGlhc190YXBfZGlzdGFuY2UgfD4gCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IAogIHBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDEpCmBgYAoKIyMjIyMjIyAqKlBhcm5hIFNlcnJhIGRvIFBhcmRvKioKCmBgYHtyfQpjdXRpYXNfcGFyX2Rpc3RhbmNlIDwtIGZpbHRyYXJfZGFkb3MoCiAgbm9tZV91Y3MgPSAicGFybmFfZGFfc2VycmFfZG9fcGFyZG8iLAogIG5vbWVfc3BzID0gImRhc3lwcm9jdGFfY3JvY29ub3RhIiwKICB2YWxpZGFjYW9fb2JzID0gImVzcGVjaWUiCil8PiAKICB0cmFuc2Zvcm1hcl9kYWRvc19mb3JtYXRvX0Rpc3RhbmNlKGFtb3N0cmFzX3JlcGV0aWRhcyA9IFRSVUUpCgpjdXRpYXNfcGFyX2Rpc3RhbmNlIHw+IAogIHBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDEpCmBgYAoKIyMjIyMjIyAqKkVzZWMgZGEgVGVycmEgZG8gTWVpbyoqCgpgYGB7cn0KY3V0aWFzX3Rlcl9kaXN0YW5jZSA8LSBmaWx0cmFyX2RhZG9zKAogIG5vbWVfdWNzID0gImVzZWNfZGFfdGVycmFfZG9fbWVpbyIsCiAgbm9tZV9zcHMgPSAiZGFzeXByb2N0YV9jcm9jb25vdGEiLAogIHZhbGlkYWNhb19vYnMgPSAiZXNwZWNpZSIKKSB8PiAKICB0cmFuc2Zvcm1hcl9kYWRvc19mb3JtYXRvX0Rpc3RhbmNlKGFtb3N0cmFzX3JlcGV0aWRhcyA9IFRSVUUpCgpjdXRpYXNfdGVyX2Rpc3RhbmNlIHw+IAogIHRpZHlyOjpkcm9wX25hKGRpc3RhbmNlKSB8PiAKICBwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIyMgKipSZXNleCBSaW96aW5obyBkbyBBbmZyw61zaW8qKgoKYGBge3J9CmN1dGlhc19hbmZfZGlzdGFuY2UgPC0gZmlsdHJhcl9kYWRvcygKICBub21lX3VjcyA9ICJyZXNleF9yaW96aW5ob19kb19hbmZyaXNpbyIsCiAgbm9tZV9zcHMgPSAiZGFzeXByb2N0YV9jcm9jb25vdGEiLAogIHZhbGlkYWNhb19vYnMgPSAiZXNwZWNpZSIKKSB8PiAKICB0cmFuc2Zvcm1hcl9kYWRvc19mb3JtYXRvX0Rpc3RhbmNlKGFtb3N0cmFzX3JlcGV0aWRhcyA9IFRSVUUpCgpjdXRpYXNfYW5mX2Rpc3RhbmNlIHw+IAogIHBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDEpCmBgYAoKIyMjIyMgQWp1c3RhbmRvIGRpZmVyZW50ZXMgbW9kZWxvcyBwYXJhIGRhZG9zIEdsb2JhaXMKClBhcmEgYWp1c3RhciBvcyBtb2RlbG9zIGFvcyBkYWRvcyBnbG9iYWlzIGUgZXN0cmF0aWZpY2Fkb3MsIG1hbnRpdmVtb3MgYSBtZXNtYSBkaXN0w6JuY2lhIGRlIHRydW5jYW1lbnRvIHBhcmEgb3MgZGFkb3MgZGFzIGN1dGlhcyBuYSBSZXNleCBUYXBhasOzcy1BcmFwaXVucywgZGUgMTAlLCB1bWEgdmV6IHF1ZSBhIGRpc3RyYnVpw6fDo28gZG9zIGRhZG9zIMOpIHNlbWVsaGFudGUgdGFudG8gbm9zIGRhZG9zIGdsb2JhaXMgY29tbyBuYXMgVUNzIGFuYWxpc2FkYXMuCgojIyMjIyMgVW5pZm9ybWUgY29tIHRlcm1vcyBkZSBhanVzdGUgQ29zc2VubyBlIHBvbGlub21pYWwgc2ltcGxlcwoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyB1bmlmb3JtZSBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2Rpc3RhbmNlX3VuaWYgPC0gY3V0aWFzX2Rpc3RhbmNlIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJ1bmlmIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKIyMjIyMjIEhhbGYtTm9ybWFsIHNlbSB0ZXJtb3MgZGUgYWp1c3RlIGUgY29tIHRlcm1vcyBkZSBhanVzdGUgQ29zc2VubyBlIFBvbGlub21pYWwgZGUgSGVybWl0ZQoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2Rpc3RhbmNlX2huIDwtIGN1dGlhc19kaXN0YW5jZSB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaG4iLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIikKYGBgCgojIyMjIyMgSGF6YXJkLXJhdGUgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZSBDb3NzZW5vIGUgUG9saW5vbWlhbCBkZSBIZXJtaXRlCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhemFyZC1yYXRlIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYXNfZGlzdGFuY2VfaHIgPC0gY3V0aWFzX2Rpc3RhbmNlIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJociIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCiMjIyMjIENvbXBhcmFuZG8gb3MgbW9kZWxvcwoKIyMjIyMjIFRhYmVsYSBjb20gbyByZXN1bW8gY29tcGFyYXRpdm8gZG9zIG1vZGVsb3MKCmBgYHtyfQptZWxob3JfbW9kZWxvX2N1dGlhcyA8LSBzZWxlY2lvbmFyX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUoCiAgY3V0aWFzX2Rpc3RhbmNlX3VuaWYkQ29zc2VubywKICBjdXRpYXNfZGlzdGFuY2VfdW5pZiRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYXNfZGlzdGFuY2VfaG4kYFNlbSB0ZXJtb2AsCiAgY3V0aWFzX2Rpc3RhbmNlX2huJENvc3Nlbm8sCiAgY3V0aWFzX2Rpc3RhbmNlX2huJGBIZXJtaXRlIHBvbGlub21pYWxgLAogIGN1dGlhc19kaXN0YW5jZV9ociRgU2VtIHRlcm1vYCwKICBjdXRpYXNfZGlzdGFuY2VfaHIkQ29zc2VubywKICBjdXRpYXNfZGlzdGFuY2VfaHIkYFBvbGlub21pYWwgc2ltcGxlc2AKKQoKbWVsaG9yX21vZGVsb19jdXRpYXMKYGBgCgojIyMjIyMgR3LDoWZpY29zIGRlIGFqdXN0ZSBkYXMgZnVuw6fDtWVzIGRlIGRldGXDp8OjbyDDoHMgcHJvYmFiaWxpZGFkZXMgZGUgZGV0ZcOnw6NvCgpgYGB7cn0KbW9kZWxvc19jdXRpYXMgPC0gZ2VyYXJfbGlzdGFfbW9kZWxvc19zZWxlY2lvbmFkb3MoCiAgY3V0aWFzX2Rpc3RhbmNlX2hyJGBTZW0gdGVybW9gLAogIGN1dGlhc19kaXN0YW5jZV9obiRDb3NzZW5vLAogIGN1dGlhc19kaXN0YW5jZV91bmlmJENvc3Nlbm8sCiAgY3V0aWFzX2Rpc3RhbmNlX3VuaWYkYFBvbGlub21pYWwgc2ltcGxlc2AsCiAgY3V0aWFzX2Rpc3RhbmNlX2huJGBTZW0gdGVybW9gLAogIG5vbWVfbW9kZWxvc19zZWxlY2lvbmFkb3MgPSBtZWxob3JfbW9kZWxvX2N1dGlhcwopCgpwbG90YXJfZnVuY2FvX2RldGVjY2FvX21vZGVsb3Nfc2VsZWNpb25hZG9zKG1vZGVsb3NfY3V0aWFzKQpgYGAKCiMjIyMjIyBUZXN0ZSBkZSBib25kYWRlIGRlIGFqdXN0ZSBkb3MgbW9kZWxvcyBlIFEtUSBwbG90cwoKYGBge3J9CiNjcmlhciB1bWEgbGlzdGEgY29tIG9zIG1vZGVsb3Mgc2VsZWNpb25hZG9zLCBuYSBvcmRlbSBkZSBzZWxlw6fDo28KdGVzdGFyX2JvbmRhZGVfYWp1c3RlKAogIG1vZGVsb3NfY3V0aWFzLAogIHBsb3QgPSBUUlVFLAogIGNoaXNxID0gRkFMU0UsCikKICAKYGBgCgpBcXVpIHPDo28gZ2VyYWRvcyBRLVEgcGxvdHMgcXVlIHBlcm1pdGVtIGF2YWxpYXIgYSBxdWFsaWRhZGUgZG8gYWp1c3RlCmRvcyBtb2RlbG9zLiBFIHRhbWLDqW0gdW1hIHRhYmVsYSBjb20gb3MgcmVzdWx0YWRvcyBkbyBDYXJtw6lyLXZvbiBNaXNlcywKb25kZSBXIMOpIG8gdmFsb3IgZG8gdGVzdGUgZSBwIHNldSB2YWxvciBkZSBzaWduaWZpY8OibmNpYS4gTmVzc2UgY2FzbywKcXVhbnRvIG1haW9yIG8gdmFsb3IgZGUgcCwgbWVsaG9yIG8gYWp1c3RlIGRvIG1vZGVsby4KCiMjIyMjIEF2YWxpYW5kbyBhcyBlc3RpbWF0aXZhcyBkZSBBYnVuZMOibmNpYSBlIERlbnNpZGFkZQoKQXF1aSwgc8OjbyByZXN1bWlkb3Mgb3MgZGFkb3MgZGUgdGF4YSBkZSBlbmNvbnRybywgYWJ1bmTDom5jaWEgZSBkZW5zaWRhZGUKZW0gdHLDqnMgdGFiZWxhcy4KCiMjIyMjIyAqKsOBcmVhIGNvYmVydGEgcGVsYSBBbW9zdHJhZ2VtKioKCmBgYHtyfQpnZXJhcl9yZXN1bHRhZG9zX0Rpc3RhbmNlKAogIGRhZG9zID0gbW9kZWxvc19jdXRpYXMsCiAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IG1lbGhvcl9tb2RlbG9fY3V0aWFzLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImFyZWFfZXN0dWRvIiwgCiAgZXN0cmF0aWZpY2FjYW8gPSBUUlVFCikKYGBgCgojIyMjIyMgKirDgWJ1bmTDom5jaWEqKgoKYGBge3J9CgpnZXJhcl9yZXN1bHRhZG9zX0Rpc3RhbmNlKAogIGRhZG9zID0gbW9kZWxvc19jdXRpYXMsCiAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IG1lbGhvcl9tb2RlbG9fY3V0aWFzLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImFidW5kYW5jaWEiLCAKICBlc3RyYXRpZmljYWNhbyA9IFRSVUUKKQoKYGBgCgojIyMjIyMgKipEZW5zaWRhZGUqKgoKYGBge3J9CgpnZXJhcl9yZXN1bHRhZG9zX0Rpc3RhbmNlKAogIGRhZG9zID0gbW9kZWxvc19jdXRpYXMsCiAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IG1lbGhvcl9tb2RlbG9fY3V0aWFzLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImRlbnNpZGFkZSIsIAogIGVzdHJhdGlmaWNhY2FvID0gVFJVRQopCgpgYGAKCiMjIyMjIEFqdXN0YW5kbyBtb2RlbG9zIHBhcmEgY2FkYSBlc3RyYXRvIGVzcGFjaWFsIChVbmlkYWRlIGRlIENvbnNlcnZhw6fDo28pCgpBIHJlZHXDp8OjbyBubyB0YW1hbmhvIGFtb3N0cmFsIGdlcmFsbWVudGUgZmF6IGNvbSBxdWUgb3MgbW9kZWxvcyBwYXJhIG9zIGRhZG9zIGdsb2JhaXMgdGVuaGFtIHVtIGFqdXN0ZSBtZWxob3IgcXVlIG9zIG1vZGVsb3MgYWp1c3RhZG9zIGFvcyBlc3RyYXRvcy4gRW50cmV0YW50bywgcGFyYSBvcyBkYWRvcyBkbyBNb25pdG9yYSwgY29uc2lkZXJhbmRvIGFsZ3VucyBydcOtZG9zIGFtb3N0cmFpcyBzb2JyZSBhIGRpc3RyaWJ1acOnw6NvIGRvcyBkYWRvcywgbyBleGNlc3NvIGRlIHJlcGV0acOnw7VlcywgcmVzdWx0YWRvcyBtZWxob3JlcyBkZSBhanVzdGUgdMOqbSBzaWRvIG9idGlkb3MgcGFyYSBjb25qdXRub3MgZGUgZGFkb3MgbWVub3Jlcy4KCk5hcyBhbsOhbGlzZXMgYW50ZXJpb3Jlcywgb3MgcGFyw6JtZXRyb3MgZGUgYWp1c3RlIGRvcyBtb2RlbG9zIGUgdmFsb3JlcyBkZSBBSUMgZm9yYW0gZ2VyYWRvcyBzb21lbnRlIHBhcmEgb3MgZGFkb3MgZ2xvYmFpcy4gUG9yw6ltLCBhcyBlc3RpbWF0aXZhcyByZWxhY2lvbmFkYXMgYSDDoXJlYSBkZSBlc3R1ZG8sIGFidW5kw6JuY2lhIGUgZGVuc2lkYWRlLCBmb3JhbSBnZXJhZGFzIHBhcmEgY2FkYSBlc3RyYXRvLgoKVW0gY3JpdMOpcmlvIHBhcmEgYXZhbGlhciBzZSBvIGFqdXN0ZSBkYXMgZnVuw6fDtWVzIHBhcmEgb3MgZGFkb3MgZXN0cmF0aWZpY2Fkb3MgZm9pIG1lbGhvciBxdWUgcGFyYSBvcyBkYWRvcyBnbG9iYWlzIMOpIGEgY29tcGFyYcOnw6NvIGRvIHNvbWF0w7NyaW8gZG9zIHZhbG9yZXMgZGUgQUlDIHBhcmEgY2FkYSBlc3RyYXRvIGNvbSBvIHZhbG9yIGRlIEFJQyBkbyBtb2RlbG8gZ2xvYmFsLiBTZSBhIHNvbWEgZG9zIHZhbG9yZXMgZGUgQUlDIGRvcyBlc3RyYXRvcyBmb3IgbWVub3IgcXVlIG8gQUlDIGdsb2JhbCwgc2lnbmlmaWNhIHF1ZSBvIGFqdXN0ZSBmb2kgbWVsaG9yIHBhcmEgb3MgZGFkb3MgZXN0cmF0aWZpY2Fkb3MuCgpBc3NpbSwgZXNjb2xoZW1vcyB1bSBkb3MgbW9kZWxvcyB0ZXN0YWRvcyBhbnRlcmlvcm1lbnRlIHBhcmEgb3MgZGFkb3MgZ2xvYmFpcywgcXVlIGZvaSBvIEhhbGYtbm9ybWFsLiBFc2NvbGhlbW9zIG8gc2VndW5kbyBtZWxob3IgbW9kZWxvIHBvcnF1ZSBjb25zaWRlcmFtb3MgcXVlIG8gYWp1c3RlIGRvIEhhemFyZC1yYXRlLCBhcGVzYXIgZGUgYXByZXNlbnRhciBvcyBtZWxob3JlcyB2YWxvcmVzIGRlIEFJQyBlIHRlc3RlIGRlIGFqdXN0ZSBkZSBib25kYWRlLCBmb2kgc2Vuc8OtdmVsIGFvIHBpY28gZGUgb2JzZXJ2YcOnw7VlcyBwcsOzeGltbyBhIHplcm8sIHN1YnN0aW1hbmRvIGFzIGVzdGltYXRpdmFzIGRlIHByb2JhYmlsaWRhZGUgZGUgZGV0ZWPDp8Ojby4gQXNzaW0sIHZhbW9zIGNvbXBhcmFyIG8gQUlDIGdsb2JhbCBwYXJhIG8gbW9kZWxvIGRvIHRpcG8gSGFsZi1ub3JtYWwgY29tIG9zIEFJQ3MgZGFzIGZ1bsOnw7VlcyBhanVzdGFkYXMgcGFyYSBvcyBkYWRvcyBkZSBjYWRhIFVuaWRhZGUgZGUgQ29uc2VydmHDp8Ojby4KCgojIyMjIyMgSGFsZi1Ob3JtYWwKCiMjIyMjIyMgKipEYWRvcyBHbG9iYWlzKioKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhc19kaXN0YW5jZV9obiA8LSBjdXRpYXNfZGlzdGFuY2UgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhuIiwKICAgIHRlcm1vc19hanVzdGUgPSAiY29zIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKIyMjIyMjIyAqKlJlc2V4IFRhcGFqw7NzLUFyYXBpdW5zKioKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhc190YXBfZGlzdGFuY2VfaG4gPC0gY3V0aWFzX3RhcF9kaXN0YW5jZSB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaG4iLAogICAgdGVybW9zX2FqdXN0ZSA9ICJjb3MiLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIikKYGBgCgojIyMjIyMjICoqUmVzZXggVGFwYWrDs3MtQXJhcGl1bnMqKgoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX3RhcF9kaXN0YW5jZV9obiA8LSBjdXRpYXNfdGFwX2Rpc3RhbmNlIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0ZXJtb3NfYWp1c3RlID0gImNvcyIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCgojIyMjIyMjICoqUGFybmEgU2VycmEgZG8gUGFyZG8qKgoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX3Bhcl9kaXN0YW5jZV9obiA8LSBjdXRpYXNfcGFyX2Rpc3RhbmNlIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0ZXJtb3NfYWp1c3RlID0gImNvcyIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCiMjIyMjIyMgKipFc2VjIGRhIFRlcnJhIGRvIE1laW8qKgoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX3Rlcl9kaXN0YW5jZV9obiA8LSBjdXRpYXNfdGVyX2Rpc3RhbmNlIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0ZXJtb3NfYWp1c3RlID0gImNvcyIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCiMjIyMjIyMgKipSZXNleCBSaW96aW5obyBkbyBBbmZyw61zaW8qKgoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2FuZl9kaXN0YW5jZV9obiA8LSBjdXRpYXNfYW5mX2Rpc3RhbmNlIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0ZXJtb3NfYWp1c3RlID0gImNvcyIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCgojIyMjIyBDb21wYXJhbmRvIG9zIG1vZGVsb3MKCiMjIyMjIyBUYWJlbGEgY29tIG8gcmVzdW1vIGNvbXBhcmF0aXZvIGRvcyBtb2RlbG9zCgpgYGB7cn0KbW9kZWxvX2N1dGlhc19lc3RyYXQgPC0gY29tcGFyYXJfYWljX21vZGVsb19lc3RyYXRpZmljYWRvKAogIGN1dGlhc19kaXN0YW5jZV9obiRDb3NzZW5vLAogIGN1dGlhc190YXBfZGlzdGFuY2VfaG4sCiAgY3V0aWFzX3Bhcl9kaXN0YW5jZV9obiwKICBjdXRpYXNfdGVyX2Rpc3RhbmNlX2huLAogIGN1dGlhc19hbmZfZGlzdGFuY2VfaG4sIAogIG5vbWVfbW9kZWxvcyA9IGMoCiAiR2xvYmFsIiwKICJSZXNleCBUYXBhasOzcy1BcmFwaXVucyIsCiAiUGFybmEgU2VycmEgZG8gUHJhZG8iLAogIkVzZWMgZGEgVGVycmEgZG8gTWVpbyIsCiAiUmVzZXggZG8gUmlvemluaG8gZG8gQW5mcsOtc2lvIgogICkKKQoKCm1vZGVsb19jdXRpYXNfZXN0cmF0CmBgYAoKIyMjIyMjIEdyw6FmaWNvcyBkZSBhanVzdGUgZGFzIGZ1bsOnw7VlcyBkZSBkZXRlw6fDo28gw6BzIHByb2JhYmlsaWRhZGVzIGRlIGRldGXDp8OjbwoKYGBge3IsIGV2YWw9RkFMU0V9Cm1vZGVsb3NfY3V0aWFzX2VzdHJhdCA8LSBnZXJhcl9saXN0YV9tb2RlbG9zX3NlbGVjaW9uYWRvcygKICBjdXRpYXNfZGlzdGFuY2VfaG4kQ29zc2VubywKICBjdXRpYXNfdGFwX2Rpc3RhbmNlX2huLAogIGN1dGlhc19wYXJfZGlzdGFuY2VfaG4sCiAgY3V0aWFzX3Rlcl9kaXN0YW5jZV9obiwKICBjdXRpYXNfYW5mX2Rpc3RhbmNlX2huLAogIG5vbWVfbW9kZWxvc19zZWxlY2lvbmFkb3MgPSBtb2RlbG9fY3V0aWFzX2VzdHJhdAopCgpwbG90YXJfZnVuY2FvX2RldGVjY2FvX21vZGVsb3Nfc2VsZWNpb25hZG9zKG1vZGVsb3NfY3V0aWFzX2VzdHJhdCkKYGBgCgojIyMgRmx1eG8gNiAtIEFtb3N0cmFnZW0gcG9yIGRpc3TDom5jaWEgZXN0cmF0aWZpY2FkYSBwb3IgYW5vCgpQYXJhIG9idGVyIGFzIGVzdGltYXRpdmFzIGFudWFpcyBkZSBkZW5zaWRhZGUgY29udGludWFyZW1vcyB1dGlsaXphbmRvIGEgYWJvcmRhZ2VtIGRvIEZsdXhvIDIsIGNvbSBhbW9zdHJhZ2VucyBzZW0gcmVwZXRpw6fDo28uCgojIyMjIENhcnJlZ2FuZG8gb3MgZGFkb3MKCkFxdWkgdmFtb3MgdHJhYmFsaGFyIGNvbSBvcyBkYWRvcyBmaWx0cmFkb3MsIHNlbSByZXBldGnDp8O1ZXMuIE8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHRvdGFsIGZvaSBkZSA1NS4KCmBgYHtyfQpjdXRpYXNfeWVhciA8LSBmaWx0cmFyX2RhZG9zKAogIG5vbWVfdWNzID0gInJlc2V4X3RhcGFqb3NfYXJhcGl1bnMiLCAKICBub21lX3NwcyA9ICJkYXN5cHJvY3RhX2Nyb2Nvbm90YSIsCiAgdmFsaWRhY2FvX29icyA9ICJlc3BlY2llIgopCgpjdXRpYXNfeWVhcl9kaXN0YW5jZSA8LSB0cmFuc2Zvcm1hcl9kYWRvc19mb3JtYXRvX0Rpc3RhbmNlKAogIGN1dGlhc195ZWFyLAogIGFtb3N0cmFzX3JlcGV0aWRhcyA9IEZBTFNFKQoKY3V0aWFzX3llYXJfZGlzdGFuY2UKYGBgCgojIyMjIyBQbG90YW5kbyBvIGhpc3RvZ3JhbWEgZGFzIGZyZXF1w6puY2lhcyBkZSBvY29ycsOqbmNpYSBwZWxhIGRpc3TDom5jaWEKIyMjIyMjIERhZG9zIEdsb2JhaXMKClBsb3RhbmRvIG8gaGlzdG9ncmFtYSBwYXJhIG9zIGRhZG9zIGdsb2JhaXMuCgpgYGB7cn0KY3V0aWFzX3llYXJfZGlzdGFuY2UgfD4gCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IApwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIyBQb3IgRXN0cmF0bwoKUGxvdGFuZG8gbyBoaXN0b2dyYW1hIHBhcmEgY2FkYSBhbm8uCgojIyMjIyMjICoqMjAxNCoqCgpgYGB7cn0KY3V0aWFfMjAxNCA8LSBjdXRpYXNfeWVhcl9kaXN0YW5jZSB8PiAKICBkcGx5cjo6ZmlsdGVyKHllYXIgPT0gMjAxNCkKCmN1dGlhXzIwMTQgfD4gCiAgcGxvdGFyX2Rpc3RyaWJ1aWNhb19kaXN0YW5jaWFfaW50ZXJhdGl2byhsYXJndXJhX2NhaXhhID0gMSkKYGBgCgojIyMjIyMjICoqMjAxNSoKCmBgYHtyfQpjdXRpYV8yMDE1IDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDE1KQoKY3V0aWFfMjAxNSB8PiAKICBwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIyMgKioyMDE2KioKCmBgYHtyfQpjdXRpYV8yMDE2IDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDE2KQoKY3V0aWFfMjAxNiB8PiAKICBwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIyMgKioyMDE3KioKCmBgYHtyfQpjdXRpYV8yMDE3IDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDE3KQoKY3V0aWFfMjAxNyB8PiAKICB0aWR5cjo6ZHJvcF9uYShkaXN0YW5jZSkgfD4gCiAgcGxvdGFyX2Rpc3RyaWJ1aWNhb19kaXN0YW5jaWFfaW50ZXJhdGl2byhsYXJndXJhX2NhaXhhID0gMSkKYGBgCgojIyMjIyMjICoqMjAxOCoqCgpgYGB7cn0KY3V0aWFfMjAxOCA8LSBjdXRpYXNfeWVhcl9kaXN0YW5jZSB8PiAKICBkcGx5cjo6ZmlsdGVyKHllYXIgPT0gMjAxOCkKCmN1dGlhXzIwMTggfD4gCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IAogIHBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDEpCmBgYAoKIyMjIyMjIyAqKjIwMTkqKgoKYGBge3J9CmN1dGlhXzIwMTkgPC0gY3V0aWFzX3llYXJfZGlzdGFuY2UgfD4gCiAgZHBseXI6OmZpbHRlcih5ZWFyID09IDIwMTkpCgpjdXRpYV8yMDE5IHw+IAogIHRpZHlyOjpkcm9wX25hKGRpc3RhbmNlKSB8PiAKICBwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIyMgKioyMDIwKioKCmBgYHtyfQpjdXRpYV8yMDIwIDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDIwKQoKY3V0aWFfMjAyMHw+IAogIHRpZHlyOjpkcm9wX25hKGRpc3RhbmNlKSB8PiAKICBwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIyMgKioyMDIxKioKCmBgYHtyfQpjdXRpYV8yMDIxIDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDIxKQoKY3V0aWFfMjAyMSB8PiAKICB0aWR5cjo6ZHJvcF9uYShkaXN0YW5jZSkgfD4gCiAgcGxvdGFyX2Rpc3RyaWJ1aWNhb19kaXN0YW5jaWFfaW50ZXJhdGl2byhsYXJndXJhX2NhaXhhID0gMSkKYGBgCgojIyMjIyBBanVzdGFuZG8gZGlmZXJlbnRlcyBtb2RlbG9zIHBhcmEgZGFkb3MgR2xvYmFpcwoKKipQYXJhIGFqdXN0YXIgb3MgbW9kZWxvcyBhb3MgZGFkb3MgZ2xvYmFpcyBlIGVzdHJhdGlmaWNhZG9zLCBtYW50aXZlbW9zIGEgbWVzbWEgZGlzdMOibmNpYSBkZSB0cnVuY2FtZW50byBwYXJhIG9zIGRhZG9zIGRhcyBjdXRpYXMgbmEgUmVzZXggVGFwYWrDs3MtQXJhcGl1bnMsIGRlIDEwJSwgdW1hIHZleiBxdWUgYSBkaXN0cmJ1acOnw6NvIGRvcyBkYWRvcyDDqSBzZW1lbGhhbnRlIHRhbnRvIG5vcyBkYWRvcyBnbG9iYWlzIGNvbW8gbmFzIFVDcyBhbmFsaXNhZGFzLioqCgojIyMjIyMgVW5pZm9ybWUgY29tIHRlcm1vcyBkZSBhanVzdGUgQ29zc2VubyBlIHBvbGlub21pYWwgc2ltcGxlcwoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyB1bmlmb3JtZSBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2Rpc3RhbmNlX3VuaWZfeWVhciA8LSBjdXRpYXNfeWVhcl9kaXN0YW5jZSB8PgogIGRwbHlyOjpmaWx0ZXIoeWVhciAhPSAyMDE0KSB8PiAKICBkcGx5cjo6bXV0YXRlKFJlZ2lvbi5MYWJlbCA9IHllYXIpIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJ1bmlmIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKIyMjIyMjIEhhbGYtTm9ybWFsIHNlbSB0ZXJtb3MgZGUgYWp1c3RlIGUgY29tIHRlcm1vcyBkZSBhanVzdGUgQ29zc2VubyBlIFBvbGlub21pYWwgZGUgSGVybWl0ZQoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2Rpc3RhbmNlX2huX3llYXIgPC0gY3V0aWFzX3llYXJfZGlzdGFuY2UgfD4gCiAgZHBseXI6OmZpbHRlcih5ZWFyICE9IDIwMTQpIHw+IAogIGRwbHlyOjptdXRhdGUoUmVnaW9uLkxhYmVsID0geWVhcikgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhuIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKIyMjIyMjIEhhemFyZC1yYXRlIHNlbSB0ZXJtb3MgZGUgYWp1c3RlIGUgY29tIHRlcm1vcyBkZSBhanVzdGUgQ29zc2VubyBlIFBvbGlub21pYWwgZGUgSGVybWl0ZQoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYXphcmQtcmF0ZSBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzX2Rpc3RhbmNlX2hyX3llYXIgPC0gY3V0aWFzX3llYXJfZGlzdGFuY2UgfD4gCiAgZHBseXI6OmZpbHRlcih5ZWFyICE9IDIwMTQpIHw+IAogIGRwbHlyOjptdXRhdGUoUmVnaW9uLkxhYmVsID0geWVhcikgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhyIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKIyMjIyMgQ29tcGFyYW5kbyBvcyBtb2RlbG9zCgojIyMjIyMgVGFiZWxhIGNvbSBvIHJlc3VtbyBjb21wYXJhdGl2byBkb3MgbW9kZWxvcwoKYGBge3J9Cm1lbGhvcl9tb2RlbG9fY3V0aWFzX3llYXIgPC0gc2VsZWNpb25hcl9mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKAogIGN1dGlhc19kaXN0YW5jZV91bmlmX3llYXIkQ29zc2VubywKICBjdXRpYXNfZGlzdGFuY2VfdW5pZl95ZWFyJGBQb2xpbm9taWFsIHNpbXBsZXNgLAogIGN1dGlhc19kaXN0YW5jZV9obl95ZWFyJGBTZW0gdGVybW9gLAogIGN1dGlhc19kaXN0YW5jZV9obl95ZWFyJENvc3Nlbm8sCiAgY3V0aWFzX2Rpc3RhbmNlX2huX3llYXIkYEhlcm1pdGUgcG9saW5vbWlhbGAsCiAgY3V0aWFzX2Rpc3RhbmNlX2hyX3llYXIkYFNlbSB0ZXJtb2AsCiAgY3V0aWFzX2Rpc3RhbmNlX2hyX3llYXIkQ29zc2VubywKICBjdXRpYXNfZGlzdGFuY2VfaHJfeWVhciRgUG9saW5vbWlhbCBzaW1wbGVzYAopCgptZWxob3JfbW9kZWxvX2N1dGlhc195ZWFyCmBgYAoKIyMjIyMjIEdyw6FmaWNvcyBkZSBhanVzdGUgZGFzIGZ1bsOnw7VlcyBkZSBkZXRlw6fDo28gw6BzIHByb2JhYmlsaWRhZGVzIGRlIGRldGXDp8OjbwoKYGBge3J9Cm1vZGVsb3NfY3V0aWFzX3llYXIgPC0gZ2VyYXJfbGlzdGFfbW9kZWxvc19zZWxlY2lvbmFkb3MoCiAgY3V0aWFzX2Rpc3RhbmNlX2huX3llYXIkQ29zc2VubywKICBjdXRpYXNfZGlzdGFuY2VfaHJfeWVhciRgU2VtIHRlcm1vYCwKICBjdXRpYXNfZGlzdGFuY2VfdW5pZl95ZWFyJENvc3Nlbm8sCiAgY3V0aWFzX2Rpc3RhbmNlX3VuaWZfeWVhciRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYXNfZGlzdGFuY2VfaG5feWVhciRgU2VtIHRlcm1vYCwKICBub21lX21vZGVsb3Nfc2VsZWNpb25hZG9zID0gbWVsaG9yX21vZGVsb19jdXRpYXNfeWVhcgopCgpwbG90YXJfZnVuY2FvX2RldGVjY2FvX21vZGVsb3Nfc2VsZWNpb25hZG9zKG1vZGVsb3NfY3V0aWFzX3llYXIpCmBgYAoKIyMjIyMjIFRlc3RlIGRlIGJvbmRhZGUgZGUgYWp1c3RlIGRvcyBtb2RlbG9zIGUgUS1RIHBsb3RzCgpgYGB7cn0KI2NyaWFyIHVtYSBsaXN0YSBjb20gb3MgbW9kZWxvcyBzZWxlY2lvbmFkb3MsIG5hIG9yZGVtIGRlIHNlbGXDp8Ojbwp0ZXN0YXJfYm9uZGFkZV9hanVzdGUoCiAgbW9kZWxvc19jdXRpYXNfeWVhciwKICBwbG90ID0gVFJVRSwKICBjaGlzcSA9IEZBTFNFLAopCiAgCmBgYAoKQXF1aSBzw6NvIGdlcmFkb3MgUS1RIHBsb3RzIHF1ZSBwZXJtaXRlbSBhdmFsaWFyIGEgcXVhbGlkYWRlIGRvIGFqdXN0ZQpkb3MgbW9kZWxvcy4gRSB0YW1iw6ltIHVtYSB0YWJlbGEgY29tIG9zIHJlc3VsdGFkb3MgZG8gQ2FybcOpci12b24gTWlzZXMsCm9uZGUgVyDDqSBvIHZhbG9yIGRvIHRlc3RlIGUgcCBzZXUgdmFsb3IgZGUgc2lnbmlmaWPDom5jaWEuIE5lc3NlIGNhc28sCnF1YW50byBtYWlvciBvIHZhbG9yIGRlIHAsIG1lbGhvciBvIGFqdXN0ZSBkbyBtb2RlbG8uCgojIyMjIyBBdmFsaWFuZG8gYXMgZXN0aW1hdGl2YXMgZGUgQWJ1bmTDom5jaWEgZSBEZW5zaWRhZGUKCkFxdWksIHPDo28gcmVzdW1pZG9zIG9zIGRhZG9zIGRlIHRheGEgZGUgZW5jb250cm8sIGFidW5kw6JuY2lhIGUgZGVuc2lkYWRlCmVtIHRyw6pzIHRhYmVsYXMuCgojIyMjIyMgKirDgXJlYSBjb2JlcnRhIHBlbGEgQW1vc3RyYWdlbSoqCgpgYGB7cn0KZ2VyYXJfcmVzdWx0YWRvc19EaXN0YW5jZSgKICBkYWRvcyA9IG1vZGVsb3NfY3V0aWFzX3llYXIsCiAgcmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IG1lbGhvcl9tb2RlbG9fY3V0aWFzX3llYXIsCiAgdGlwb19kZV9yZXN1bHRhZG8gPSAiYXJlYV9lc3R1ZG8iLCAKICBlc3RyYXRpZmljYWNhbyA9IFRSVUUKKQpgYGAKCiMjIyMjIyAqKsOBYnVuZMOibmNpYSoqCgpgYGB7cn0KcmVzdWx0YWRvX2FidW5kYW5jaWEgPC0gCmdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgZGFkb3MgPSBtb2RlbG9zX2N1dGlhc195ZWFyLAogIHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBtZWxob3JfbW9kZWxvX2N1dGlhc195ZWFyLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImFidW5kYW5jaWEiLCAKICBlc3RyYXRpZmljYWNhbyA9IFRSVUUKKQoKcmVzdWx0YWRvX2FidW5kYW5jaWEKYGBgCgpgYGB7cn0KcmVzdWx0YWRvX2FidW5kYW5jaWEgfD4KICBkcGx5cjo6bXV0YXRlKGFubyA9IGFzLmludGVnZXIoUmVnaWFvKSkgfD4gCiAgZHBseXI6Omdyb3VwX2J5KGFubykgfD4gCiAgZHBseXI6OnN1bW1hcmlzZShuID0gc3VtKGBBYnVuZGFuY2lhIGVzdGltYWRhYCkpIHw+IAogIGdncGxvdDI6OmdncGxvdCgpICsKICBnZ3Bsb3QyOjphZXMoCiAgICB4ID0gYW5vLAogICAgeSA9IG4KICApICsgCiAgZ2dwbG90Mjo6Z2VvbV9saW5lKCkgKwogIGdncGxvdDI6OnRoZW1lX21pbmltYWwoKQpgYGAKCiMjIyMjIyAqKkRlbnNpZGFkZSoqCgpgYGB7cn0KcmVzdWx0YWRvc19kZW5zaWRhZGUgPC0gCmdlcmFyX3Jlc3VsdGFkb3NfRGlzdGFuY2UoCiAgZGFkb3MgPSBtb2RlbG9zX2N1dGlhc195ZWFyLAogIHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBtZWxob3JfbW9kZWxvX2N1dGlhc195ZWFyLAogIHRpcG9fZGVfcmVzdWx0YWRvID0gImRlbnNpZGFkZSIsIAogIGVzdHJhdGlmaWNhY2FvID0gVFJVRQopCgpyZXN1bHRhZG9zX2RlbnNpZGFkZQpgYGAKCmBgYHtyfQpyZXN1bHRhZG9zX2RlbnNpZGFkZSB8PgogIGRwbHlyOjpmaWx0ZXIoUm90dWxvICE9ICJUb3RhbCIpIHw+IAogIGRwbHlyOjptdXRhdGUoYW5vID0gYXMuaW50ZWdlcihSb3R1bG8pKSB8PiAKICBnZ3Bsb3QyOjpnZ3Bsb3QoKSArCiAgZ2dwbG90Mjo6YWVzKAogICAgeCA9IGFubywKICAgIHkgPSBgRXN0aW1hdGl2YSBkZSBkZW5zaWRhZGVgCiAgKSArIAogIGdncGxvdDI6Omdlb21fbGluZSgpICsKICBnZ3Bsb3QyOjpmYWNldF93cmFwKGZhY2V0cyA9IGdncGxvdDI6OnZhcnMoTW9kZWxvKSkgKwogIGdncGxvdDI6OnRoZW1lX21pbmltYWwoKQpgYGAKCiMjIyMjIEFqdXN0YW5kbyBtb2RlbG9zIHBhcmEgY2FkYSBlc3RyYXRvIHRlbXBvcmFsIChhbm8pCgojIyMjIyMgSGFsZi1Ob3JtYWwKCiMjIyMjIyMgKipEYWRvcyBHbG9iYWlzKioKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhc19kaXN0YW5jZV95ZWFyX2huIDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0ZXJtb3NfYWp1c3RlID0gImNvcyIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCiMjIyMjIyMgKioyMDE1KioKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhc18yMDE1X2Rpc3RhbmNlX2huIDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDE1KSB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaG4iLAogICAgdGVybW9zX2FqdXN0ZSA9ICJjb3MiLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIikKYGBgCgojIyMjIyMjICoqMjAxNioqCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhbGYtbm9ybWFsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYXNfMjAxNl9kaXN0YW5jZV9obiA8LSBjdXRpYXNfeWVhcl9kaXN0YW5jZSB8PiAKICBkcGx5cjo6ZmlsdGVyKHllYXIgPT0gMjAxNikgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhuIiwKICAgIHRlcm1vc19hanVzdGUgPSAiY29zIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKCiMjIyMjIyMgKioyMDE3KioKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhc18yMDE3X2Rpc3RhbmNlX2huIDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDE3KSB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaG4iLAogICAgdGVybW9zX2FqdXN0ZSA9ICJjb3MiLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIikKYGBgCgojIyMjIyMjICoqMjAxOCoqCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhbGYtbm9ybWFsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYXNfMjAxOF9kaXN0YW5jZV9obiA8LSBjdXRpYXNfeWVhcl9kaXN0YW5jZSB8PiAKICBkcGx5cjo6ZmlsdGVyKHllYXIgPT0gMjAxOCkgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhuIiwKICAgIHRlcm1vc19hanVzdGUgPSAiY29zIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKIyMjIyMjIyAqKjIwMTkqKgoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFzXzIwMTlfZGlzdGFuY2VfaG4gPC0gY3V0aWFzX3llYXJfZGlzdGFuY2UgfD4gCiAgZHBseXI6OmZpbHRlcih5ZWFyID09IDIwMTkpIHw+IAogIGFqdXN0YXJfbW9kZWxvc19EaXN0YW5jZSgKICAgIGZ1bmNhb19jaGF2ZSA9ICJobiIsCiAgICB0ZXJtb3NfYWp1c3RlID0gImNvcyIsCiAgICB0cnVuY2FtZW50byA9ICIxMCUiKQoKYGBgCgojIyMjIyMjICoqMjAyMCoqCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhbGYtbm9ybWFsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYXNfMjAyMF9kaXN0YW5jZV9obiA8LSBjdXRpYXNfeWVhcl9kaXN0YW5jZSB8PiAKICBkcGx5cjo6ZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gCiAgYWp1c3Rhcl9tb2RlbG9zX0Rpc3RhbmNlKAogICAgZnVuY2FvX2NoYXZlID0gImhuIiwKICAgIHRlcm1vc19hanVzdGUgPSAiY29zIiwKICAgIHRydW5jYW1lbnRvID0gIjEwJSIpCgpgYGAKCiMjIyMjIyMgKioyMDIxKioKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhc18yMDIxX2Rpc3RhbmNlX2huIDwtIGN1dGlhc195ZWFyX2Rpc3RhbmNlIHw+IAogIGRwbHlyOjpmaWx0ZXIoeWVhciA9PSAyMDIxKSB8PiAKICBhanVzdGFyX21vZGVsb3NfRGlzdGFuY2UoCiAgICBmdW5jYW9fY2hhdmUgPSAiaG4iLAogICAgdGVybW9zX2FqdXN0ZSA9ICJjb3MiLAogICAgdHJ1bmNhbWVudG8gPSAiMTAlIikKCmBgYAoKIyMjIyMgQ29tcGFyYW5kbyBvcyBtb2RlbG9zCgojIyMjIyMgVGFiZWxhIGNvbSBvIHJlc3VtbyBjb21wYXJhdGl2byBkb3MgbW9kZWxvcwoKYGBge3J9Cm1vZGVsb19jdXRpYXNfZXN0cmF0X3llYXIgPC0gY29tcGFyYXJfYWljX21vZGVsb19lc3RyYXRpZmljYWRvKAogIGN1dGlhc19kaXN0YW5jZV95ZWFyX2huLAogIGN1dGlhc18yMDE1X2Rpc3RhbmNlX2huLAogIGN1dGlhc18yMDE2X2Rpc3RhbmNlX2huLAogIGN1dGlhc18yMDE3X2Rpc3RhbmNlX2huLAogIGN1dGlhc18yMDE4X2Rpc3RhbmNlX2huLCAKICBjdXRpYXNfMjAxOV9kaXN0YW5jZV9obiwgCiAgY3V0aWFzXzIwMjBfZGlzdGFuY2VfaG4sIAogIGN1dGlhc18yMDIxX2Rpc3RhbmNlX2huLCAKICBub21lX21vZGVsb3MgPSBjKAogIkdsb2JhbCIsCiAiMjAxNSIsCiAiMjAxNiIsCiAiMjAxNyIsCiAiMjAxOCIsCiAiMjAxOSIsCiAiMjAyMCIsCiAiMjAyMSIKICApCikKCgptb2RlbG9fY3V0aWFzX2VzdHJhdF95ZWFyCmBgYAoKIyMjIyMjIEdyw6FmaWNvcyBkZSBhanVzdGUgZGFzIGZ1bsOnw7VlcyBkZSBkZXRlw6fDo28gw6BzIHByb2JhYmlsaWRhZGVzIGRlIGRldGXDp8OjbwoKYGBge3IsIGV2YWw9RkFMU0V9Cm1vZGVsb3NfY3V0aWFzX2VzdHJhdCA8LSBnZXJhcl9saXN0YV9tb2RlbG9zX3NlbGVjaW9uYWRvcygKICBjdXRpYXNfZGlzdGFuY2VfeWVhcl9obiwKICBjdXRpYXNfMjAxNV9kaXN0YW5jZV9obiwKICBjdXRpYXNfMjAxNl9kaXN0YW5jZV9obiwKICBjdXRpYXNfMjAxN19kaXN0YW5jZV9obiwKICBjdXRpYXNfMjAxOF9kaXN0YW5jZV9obiwKICBjdXRpYXNfMjAxOV9kaXN0YW5jZV9obiwKICBjdXRpYXNfMjAyMF9kaXN0YW5jZV9obiwKICBjdXRpYXNfMjAyMV9kaXN0YW5jZV9obiwKICBub21lX21vZGVsb3Nfc2VsZWNpb25hZG9zID0gbW9kZWxvX2N1dGlhc19lc3RyYXQKKQoKcGxvdGFyX2Z1bmNhb19kZXRlY2Nhb19tb2RlbG9zX3NlbGVjaW9uYWRvcyhtb2RlbG9zX2N1dGlhc19lc3RyYXQpCmBgYAoK